La vraie différence entre “int” et “unsigned int”

int :

Le type de données int 32 bits peut contenir des valeurs entières comsockets entre -2 147 483 648 et 2 147 483 647. Vous pouvez également désigner ce type de données comme étant signé int ou signé.

non signé int :

Le type de données int non signé 32 bits peut contenir des valeurs entières comsockets entre 0 et 4 294 967 295. Vous pouvez également appeler ce type de données simplement comme non signé.

Ok, mais en pratique:

int x = 0xFFFFFFFF; unsigned int y = 0xFFFFFFFF; printf("%d, %d, %u, %u", x, y, x, y); // -1, -1, 4294967295, 4294967295 

aucune différence, Oo je suis un peu confus.

Héhé. Vous avez une dissortingbution implicite ici, car vous indiquez à printf quel type s’attendre.

Essayez plutôt la taille suivante:

 unsigned int x = 0xFFFFFFFF; int y = 0xFFFFFFFF; if (x < 0) printf("one\n"); else printf("two\n"); if (y < 0) printf("three\n"); else printf("four\n"); 

Oui, car dans votre cas, ils utilisent la même représentation .

Le modèle de bit 0xFFFFFFFF se présente comme -1 s’il est interprété comme un entier signé 32b et comme 4294967295 lorsqu’il est interprété comme un entier non signé 32b.

C’est la même chose que char c = 65 . Si vous l’interprétez comme un entier signé, vous obtenez 65. Si vous l’interprétez comme un caractère, c’est a .


Comme R et pmg l’ont fait remarquer, techniquement, le fait de passer des arguments qui ne correspondent pas aux spécificateurs de format est un comportement non défini. Ainsi, le programme peut faire n’importe quoi (de l’impression aléatoire à l’impression de la “bonne” chose, etc.).

La norme l’indique en 7.19.6.1-9

Si une spécification de conversion est invalide, le comportement n’est pas défini. Si l’un des arguments n’est pas du type correct pour la spécification de conversion correspondante, le comportement est indéfini.

Il n’y a pas de différence entre les deux en ce qui concerne la manière dont ils sont stockés dans la mémoire et les registres, il n’y a pas de version signée et non signée des registres int. Il n’y a pas d’informations signées stockées avec l’int. La version signée et non signée des opérations mathématiques intégrées à la CPU et la signature signent au compilateur la version à utiliser.

Le problème est que vous avez invoqué le comportement non défini .


Lorsque vous invoquez UB, tout peut arriver.

Les affectations sont ok; il y a une conversion implicite dans la première ligne

 int x = 0xFFFFFFFF; unsigned int y = 0xFFFFFFFF; 

Cependant, l’appel à printf n’est pas correct

 printf("%d, %d, %u, %u", x, y, x, y); 

Il appartient à UB de ne pas associer le spécificateur % et le type de l’argument.
Dans votre cas, vous spécifiez 2 int s et 2 unsigned int s dans cet ordre en fournissant 1 int , 1 unsigned int , 1 int et 1 unsigned int .


Ne fais pas UB !

La représentation interne de int et unsigned int est la même.

Par conséquent, lorsque vous transmettez le même format à printf il sera imprimé de la même manière.

Cependant, il existe des différences lorsque vous les comparez. Considérer:

 int x = 0x7FFFFFFF; int y = 0xFFFFFFFF; x < y // false x > y // true (unsigned int) x < (unsigned int y) // true (unsigned int) x > (unsigned int y) // false 

Cela peut également être un inconvénient, car lors de la comparaison d’entiers signés et non signés, l’un d’eux sera implicitement converti pour correspondre aux types.

Il demande à propos de la vraie différence. Lorsque vous parlez de comportement non défini, vous bénéficiez du niveau de garantie fourni par la spécification de langue – c’est loin de la réalité. Pour comprendre la vraie différence, veuillez vérifier cet extrait (bien sûr, il s’agit d’UB, mais il est parfaitement défini sur votre compilateur préféré):

 #include  int main() { int i1 = ~0; int i2 = i1 >> 1; unsigned u1 = ~0; unsigned u2 = u1 >> 1; printf("int : %X -> %X\n", i1, i2); printf("unsigned int: %X -> %X\n", u1, u2); } 

le type vous indique simplement ce que le motif de bits est censé représenter. les morceaux ne sont que ce que vous en faites. les mêmes séquences peuvent être interprétées de différentes manières.

La fonction printf interprète la valeur que vous lui transmettez en fonction du spécificateur de format dans une position correspondante. Si vous dites à printf que vous passez un int , mais que vous passez unsigned , printf réinterprétera l’un comme l’autre et imprimera les résultats que vous voyez.

Celui-ci est plutôt simple. La représentation binary est la clé qui est mentionnée mais jamais affichée. Non signé en HEX si 0XFFFFFFF = code machine = 1111 1111 1111 1111 1111 1111 1111 1111 = 4 294 967 295 représentations positives d’un nombre. C’est très bien, mais nous avons besoin d’un moyen de représenter des nombres négatifs. Ainsi, les cerveaux ont décidé de compléter le couple. Qu’est-ce que cela signifie bien? En bref, ils ont pris le chiffre le plus à gauche et ont décidé que lorsqu’il s’agit d’un 1 (suivi de tous jusqu’à ce que vous atteigniez le bit le plus significatif à gauche), le nombre sera négatif s’il est 0, il est positif. Maintenant regardons ce qui se passe 0000 0000 0000 0000 0000 0000 0000 0011 = 3 . Ajoutons maintenant à ce nombre 0111 1111 1111 1111 1111 1111 1111 1111 = 2.147.483.645, le nombre positif le plus élevé avec un entier signé. Ajoutons 1 (ici, vous voudrez peut-être rechercher une addition binary), nous devons effectuer celle-ci de bout en bout. 1111 1111 1111 1111 1111 1111 1111 1110 = -1 Donc, je suppose que nous pourrions dire que la différence est celle qui permet les nombres négatifs, ce qui est dû au bit de signe ou au bit le plus à gauche ou au bit le plus significatif.