Voir cet extrait de code
int main()
{
unsigned int a = 1000;
int b = -1;
if (a>b) printf("A is BIG! %d\n", a-b);
else printf("a is SMALL! %d\n", a-b);
return 0;
}
Cela donne la sortie: a est SMALL: 1001
Je ne comprends pas ce qui se passe ici. Comment fonctionne l'opérateur> ici? Pourquoi "a" est-il plus petit que "b"? S'il est effectivement plus petit, pourquoi ai-je un nombre positif (1001) comme différence?
Les opérations binaires entre différents types d'intégraux sont effectuées au sein d'un type "commun" défini par les conversions arithmétiques usuelles (voir la spécification de langage, 6.3.1.8). Dans votre cas, le type "commun" est unsigned int
. Cela signifie que l'opérande int
(votre b
) sera converti en unsigned int
avant la comparaison, ainsi que dans le but d'effectuer une soustraction.
Lorsque -1
est converti en unsigned int
, le résultat est la valeur maximale possible de unsigned int
(identique à UINT_MAX
). Inutile de dire que cela va être supérieur à votre valeur 1000
non signée, ce qui signifie que a > b
est en effet faux et que a
est bien small par rapport à (unsigned) b
. La if
de votre code doit être résolue en une branche else
, qui correspond à ce que vous avez observé dans votre expérience.
Les mêmes règles de conversion s'appliquent à la soustraction. Votre a-b
est réellement interprété comme étant a - (unsigned) b
et le résultat est de type unsigned int
. Une telle valeur ne peut pas être imprimée avec le spécificateur de format %d
, car %d
fonctionne uniquement avec les valeurs signed. Votre tentative d'imprimer avec %d
entraîne un comportement indéfini, de sorte que la valeur que vous voyez imprimer (même si elle a une explication déterministe logique) est totalement dépourvue de sens du point de vue du langage C.
Edit: En fait, je pourrais me tromper à propos du comportement non défini. Selon la spécification du langage C, la partie commune de la plage du type entier signé et non signé doit avoir une représentation identique (impliquant, conformément à la note de bas de page 31, "l'interchangeabilité en tant qu'arguments des fonctions"). Ainsi, le résultat de l'expression a - b
est unsigned 1001
comme décrit ci-dessus et, sauf si quelque chose me manque, il est légal d'imprimer cette valeur non signée spécifique avec le spécificateur %d
, car elle se situe dans la plage positive de int
. Imprimer (unsigned) INT_MAX + 1
avec %d
ne serait pas défini, mais 1001u
suffirait.
Sur une implémentation typique où int
est 32 bits, -1 lors de la conversion en unsigned int
est 4 294 967 295, ce qui est bien supérieur à 1000.
Même si vous traitez la soustraction dans un monde unsigned
, 1000 - (4,294,967,295) = -4,294,966,295 = 1,001
qui correspond à ce que vous obtenez.
C'est pourquoi gcc
crachera un avertissement lorsque vous comparerez unsigned
à signed
. (Si vous ne voyez pas d'avertissement, passez l'indicateur -Wsign-compare
.)
#include<stdio.h>
int main()
{
int a = 1000;
signed int b = -1, c = -2;
printf("%d",(unsigned int)b);
printf("%d\n",(unsigned int)c);
printf("%d\n",(unsigned int)a);
if(1000>-1){
printf("\ntrue");
}
else
printf("\nfalse");
return 0;
}
Pour cela, vous devez comprendre la priorité des opérateurs
Les opérateurs relationnels travaillent de gauche à droite ...
si (1000> -1)
puis tout d’abord, il passera -1 en entier non signé parce que int est considéré par défaut comme un nombre non signé et qu’il est supérieur au nombre signé
-1 deviendra le nombre non signé, il se changera en un très grand nombre
Vous effectuez une comparaison non signée, c’est-à-dire une comparaison de 1000 à 2 ^ 32 - 1.
La sortie est signée à cause de% d dans printf.
N.B. Parfois, le comportement lorsque vous mélangez des opérandes signés et non signés est spécifique au compilateur. Je pense qu'il est préférable de les éviter et de lancer des sorts en cas de doute.
Le matériel est conçu pour comparer signature à signature et non signée à non signée.
Si vous souhaitez obtenir le résultat arithmétique, convertissez d'abord la valeur non signée en un type signé plus grand. Sinon, le compilateur supposera que la comparaison se fait réellement entre des valeurs non signées.
Et -1 est représenté par 1111..1111, ce qui en fait une très grande quantité ... Le plus grand ... Lorsqu'il est interprété comme non signé.
Trouvez un moyen facile de comparer, peut-être utile lorsque vous ne pouvez pas vous débarrasser de la déclaration non signée ((par exemple, [NSArray count])), il suffit de forcer le "unsigned int" à un "int".
S'il vous plait corrigez moi si je me trompe.
if (((int)a)>b) {
....
}