Pourquoi un int négatif est-il supérieur à unsigned int?

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.