int main(void) { unsigned int y = 10; int x = – 4; if (x > y) Printf("x is greater"); else Printf("y is greater"); getch(); return (0); } Output: x is greater
Je pensais que la sortie serait y est plus grande puisqu’elle n’est pas signée. Quelle est la raison derrière cela?
Parce que la valeur int
est promue en un unsigned int
. spécifiquement 0xFFFFFFFC
sur une machine 32 bits, qui, en tant que unsigned int
est 4294967292
, considérablement plus grande que 10
C99 6.3.1.1-p2
Si un int peut représenter toutes les valeurs du type d’origine (restreint par la largeur, pour un champ binary), la valeur est convertie en un int; sinon, il est converti en un int non signé . Celles-ci s’appellent les promotions d’entier. Tous les autres types ne sont pas modifiés par les promotions en nombre entier.
Pour effectuer la conversion:
C99 6.3.1.3-p2
Sinon, si le nouveau type n’est pas signé, la valeur est convertie en ajoutant ou en soustrayant de manière répétée un de plus que la valeur maximale pouvant être représentée dans le nouveau type jusqu’à ce que la valeur soit dans la plage du nouveau type.
Ce qui signifie en gros “append UINT_MAX + 1” (comme je l’ai lu, de toute façon).
Concernant la raison pour laquelle la promotion était destinée au côté unsigned int
; priorité:
C99 6.3.1.8-P1
… Sinon, si l’opérande qui a un type entier non signé a un rang supérieur ou égal au rang du type de l’autre opérande, l’opérande avec un type entier signé est converti dans le type de l’opérande avec un type entier non signé.
Sinon, si le type de l’opérande avec un type d’entier signé peut représenter toutes les valeurs du type de l’opérande avec un type d’entier non signé, l’opérande avec un type d’entier non signé est convertie dans le type de l’opérande avec un type d’entier signé.
Ce qui me dit int
vs unsigned char
devrait fonctionner comme prévu.
Tester
int main() { int x = -4; unsigned int y = 10; unsigned char z = 10; if (x > y) printf("x>y\n"); else printf("x z) printf("x>z\n"); else printf("x
Sortie
x>y x
Eh bien regardez ça.
Une comparaison entre une valeur signée et une valeur non signée sera effectuée dans “espace non signé”. Par exemple, la valeur signée sera convertie en unsigned en ajoutant UINT_MAX + 1
. Dans la mise en œuvre en utilisant le complément 2 pour les valeurs négatives, aucune gestion spéciale des valeurs n’est requirejse sous le capot.
Dans cet exemple, le -4
est transformé en 0x100000000-4
= 0xFFFFFFFC
qui est clairement > 10
.
Lorsque vous comparez deux valeurs en C, elles doivent toutes deux être du même type. Dans ce cas ( int
et unsigned int
), la valeur int
sera d’abord convertie en un unsigned int
.
Deuxièmement, l’arithmétique entière non signée dans C est effectuée modulo la valeur maximale de ce type + 1 (c’est-à-dire qu’elle “contourne” donc UINT_MAX + 1
est à nouveau 0
et vice versa). Par conséquent, la conversion des valeurs négatives en valeurs non signées donne un très grand nombre.
La section pertinente de la norme dit:
6.3.1.3 Entiers signés et non signés
2
Sinon, si le nouveau type n’est pas signé, la valeur est convertie en ajoutant ou en soustrayant de manière répétée un de plus que la valeur maximale pouvant être représentée dans le nouveau type jusqu’à ce que la valeur soit dans la plage du nouveau type.
Lorsque vous comparez un int
et un unsigned int
l’ int
est converti en unsigned int
. La conversion d’un int
en un unsigned int
se fait en ajoutant UINT_MAX+1
(notez que votre int
est négatif). Donc, en réalité, vous comparez:
if (-3 + UINT_MAX > 10) //Since -4 is converted to UINT_MAX+1-4
Ce qui est vrai.
Le premier bit d’une valeur int permet de définir s’il s’agit d’une valeur positive ou négative. (1 = négatif, 0 positif) Vos deux variables sont converties en unsigned int avant la comparaison, où le 1 du premier bit sera interprété comme faisant partie de votre numéro.
ce code devrait fonctionner correctement:
int main(void) { unsigned int y = 10; int x = – 4; if (x > (int) y) Printf("x is greater"); else Printf ("y is greater"); getch ( ); return (0); }
int x = -4 (complément à 2 de 4 est 1111 1100 = 252) et unsigned int y = 10 est (0000 1010 = 10), donc 252> 10 donc -4 est supérieur à 10.