J'ai le code suivant:
#include <stdio.h>
int main() {
unsigned int a = -1;
int b = -1;
printf("%x\n", a);
printf("%x\n", b);
printf("%d\n", a);
printf("%d\n", b);
printf("%u\n", a);
printf("%u\n", b);
return 0;
}
La sortie est:
ffffffff
ffffffff
-1
-1
4294967295
4294967295
Je peux voir qu'une valeur est interprétée comme signée ou non signée en fonction de la valeur passée à la fonction printf
. Dans les deux cas, les octets sont les mêmes (ffffffff
). Alors, à quoi sert le mot unsigned
?
Affectez un int -1
à une unsigned
: Comme -1
ne correspond pas à la plage [0...UINT_MAX]
, des multiples de UINT_MAX+1
sont ajoutés jusqu'à ce que la réponse soit dans la plage. Evidemment, UINT_MAX
est pow(2,32)-1 or 429496725
sur la machine de l'OP, donc a
a la valeur 4294967295.
unsigned int a = -1;
Le spécificateur "%x"
, "%u"
s'attend à une unsigned
correspondante. Comme ils ne correspondent pas, "Si une spécification de conversion n'est pas valide, 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 non défini." C11 §7.21.6.1 9. Le spécificateur printf ne change pas b
.
printf("%x\n", b); // UB
printf("%u\n", b); // UB
Le spécificateur "%d"
s'attend à une int
correspondante. Puisque ceux-ci ne correspondent pas, plus UB.
printf("%d\n", a); // UB
Compte tenu d'un comportement non défini, les conclusions ne sont pas supportées.
dans les deux cas, les octets sont les mêmes (ffffffff).
Même avec le même motif binaire, différents types peuvent avoir des valeurs différentes. ffffffff
en tant que unsigned
a la valeur 4294967295. En tant que int
, en fonction du codage de l'entier signé, il a pour valeur -1, -2147483647 ou TBD. En tant que float
, il peut s'agir d'un NAN .
à quoi sert Word non signé?
unsigned
stocke un nombre entier dans la plage [0 ... UINT_MAX]
. Il n'a jamais de valeur négative. Si le code nécessite un nombre non négatif, utilisez unsigned
. Si le code nécessite un nombre de comptage pouvant être +, - ou 0, utilisez int
.
Mise à jour: pour éviter un avertissement du compilateur concernant l'affectation d'une int
signée à unsigned
, utilisez la méthode ci-dessous. Ceci est une unsigned
1u
en cours de négation - ce qui est bien défini comme ci-dessus. L'effet est identique à -1
, mais transmet les intentions directes du compilateur.
unsigned int a = -1u;
Avoir unsigned
dans la déclaration de variable est plus utile pour les programmeurs eux-mêmes - ne traitez pas les variables comme négatives. Comme vous l'avez remarqué, -1
et 4294967295
ont exactement la même représentation binaire pour un entier de 4 octets. Tout dépend de la façon dont vous voulez traiter ou les voir.
L'instruction unsigned int a = -1;
est en train de convertir -1
en complément à deux et d'assigner la représentation binaire dans a
. Les spécificateurs printf()
, x
, d
et u
montrent comment la représentation binaire stockée dans la variable a
se présente sous un format différent.
Lorsque vous initialisez unsigned int a to -1;
, cela signifie que vous stockez le complément 2's
de -1
dans la mémoire de a
.
Ce qui n'est rien d'autre que 0xffffffff
ou 4294967295
.
Par conséquent, lorsque vous l'imprimez en utilisant le spécificateur de format %x or %u
, vous obtenez cette sortie.
En spécifiant la signature d'une variable pour décider de la limite minimale et maximale de valeur pouvant être stockée.
Comme avec unsigned int
: la plage est de 0 to 4,294,967,295
et int
: la plage est de -2,147,483,648 to 2,147,483,647
Pour plus d'informations sur la signature, référez-vous this