Quelle est la difference entre signed et unsigned int?
Comme vous le savez probablement, les int
s sont stockés en interne en binaire. En règle générale, une variable int
contient 32 bits, mais dans certains environnements, elle peut en contenir 16 ou 64 bits (ou même un nombre différent, généralement mais pas nécessairement une puissance de deux).
Mais pour cet exemple, examinons les entiers 4 bits. Minuscule, mais utile à des fins d'illustration.
Comme il existe quatre bits dans un tel entier, il peut prendre l'une des 16 valeurs; 16 est deux à la quatrième puissance, ou 2 fois 2 fois 2 fois 2. Quelles sont ces valeurs? La réponse dépend de si cet entier est un signed int
ou un unsigned int
. Avec un unsigned int
, la valeur n’est jamais négative; il n'y a pas de signe associé à la valeur. Voici les 16 valeurs possibles d'un unsigned int
à quatre bits:
bits value
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 10
1011 11
1100 12
1101 13
1110 14
1111 15
... et Voici les 16 valeurs possibles d'un signed int
à quatre bits:
bits value
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 -8
1001 -7
1010 -6
1011 -5
1100 -4
1101 -3
1110 -2
1111 -1
Comme vous pouvez le constater, pour signed int
s, le bit le plus significatif est 1
si et seulement si le nombre est négatif. C'est pourquoi, pour signed int
s, ce bit est appelé "bit de signe".
int
et unsigned int
sont deux types entiers distincts. (int
peut aussi être appelé signed int
, ou simplement signed
; unsigned int
peut aussi être appelé unsigned
.)
Comme le nom l'indique, int
est un type entier signé et unsigned int
est un type entier unsigned. Cela signifie que int
est capable de représenter des valeurs négatives et unsigned int
ne peut représenter que des valeurs non négatives.
Le langage C impose certaines exigences aux gammes de ces types. La plage de int
doit être au moins -32767
.. +32767
et la plage de unsigned int
doit être au moins 0
.. 65535
. Cela implique que les deux types doivent avoir au moins 16 bits. Ils sont 32 bits sur de nombreux systèmes, voire 64 bits sur certains. int
a généralement une valeur négative supplémentaire en raison de la représentation du complément de deux utilisée par la plupart des systèmes modernes.
La différence la plus importante est peut-être le comportement de l'arithmétique signé par rapport à l'arithmétique non signée. Pour int
signé, le dépassement de capacité a un comportement indéfini. Pour unsigned int
, il n'y a pas de dépassement de capacité; toute opération générant une valeur en dehors de la plage du type est renvoyée, ainsi, par exemple, UINT_MAX + 1U == 0U
.
Tout type entier, signé ou non signé, modélise une sous-gamme de l'ensemble infini d'entiers mathématiques. Tant que vous travaillez avec des valeurs comprises dans la plage d'un type, tout fonctionne. Lorsque vous approchez la limite inférieure ou supérieure d'un type, vous rencontrez une discontinuité et vous pouvez obtenir des résultats inattendus. Pour les types entiers signés, les problèmes ne surviennent que pour de très grandes valeurs négatives et positives, dépassant INT_MIN
et INT_MAX
. Pour les types entiers non signés, des problèmes surviennent pour les très grandes valeurs positives et à zéro . Cela peut être une source de bugs. Par exemple, ceci est une boucle infinie:
for (unsigned int i = 10; i >= 0; i --) [
printf("%u\n", i);
}
parce que i
est toujours supérieur ou égal à zéro; c'est la nature des types non signés. (Dans la boucle, lorsque i
est égal à zéro, i--
définit sa valeur sur UINT_MAX
.)
Parfois, nous savons d'avance que la valeur stockée dans une variable entière donnée sera toujours positive, lorsqu'elle sera utilisée uniquement pour compter, par exemple. Dans un tel cas, nous pouvons déclarer la variable non signée, comme dans unsigned int num student;
. Avec une telle déclaration, la plage de valeurs entières admissibles (pour un compilateur 32 bits) passera de la plage -2147483648 à +2147483647 à la plage 0 à 4294967295. Ainsi, déclarer un entier comme non signé double presque la taille du plus grand valeur qu'il peut autrement contenir.
En termes simples, un unsigned int est un entier qui ne peut pas être négatif et a donc une plage de valeurs positives plus élevée qu'il peut assumer. Un entier signé est un entier qui peut être négatif mais qui a une plage positive inférieure en échange de plus de valeurs négatives qu'il peut prendre.
En pratique, il y a deux différences:
cout
en C++ ou printf
en C): la représentation en bits de nombre entier non signé est interprétée comme un entier non négatif par les fonctions d'impression.ce code peut identifier l'entier à l'aide du critère de classement:
char a = 0;
a--;
if (0 < a)
printf("unsigned");
else
printf("signed");