Quelle est la différence entre les entiers signés et non signés?
Quelle est la différence entre les entiers signés et non signés?
Réponses:
Comme vous le savez probablement, les int
s sont stockés en interne en binaire. En général, un int
contient 32 bits, mais dans certains environnements, il peut 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, regardons les entiers 4 bits. Minuscule, mais utile à des fins d'illustration.
Puisqu'il y a quatre bits dans un tel entier, il peut prendre l'une des 16 valeurs; 16 correspond à deux à la quatrième puissance, soit 2 fois 2 fois 2 fois 2. Quelles sont ces valeurs? La réponse dépend de si cet entier est a signed int
ou an unsigned int
. Avec an unsigned int
, la valeur n'est jamais négative; il n'y a aucun signe associé à la valeur. Voici les 16 valeurs possibles d'un quatre bits unsigned int
:
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 quatre bits signed int
:
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 voir, 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".
(unsigned)(-1)
doit être la valeur maximale représentable pour unsigned
(indépendamment de la représentation binaire), ce qui est trivialement vrai pour le complément à 2, mais pas pour les autres représentations.
int
et unsigned int
sont deux types d'entiers distincts. ( int
peut également être appelé signed int
, ou simplementsigned
; unsigned int
peut également être appelé unsigned
.)
Comme les noms l'impliquent, int
est un type entier signé , et unsigned int
est un non signé type entier . Cela signifie qu'il int
peut 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 sur les plages de ces types. La plage de int
doit être d'au moins -32767
.. +32767
et la plage de unsigned int
doit être d'au moins 0
..65535
. Cela implique que les deux types doivent être d'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 à 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ée et non signée. Pour signé int
, le débordement a un comportement non défini. Car unsigned int
, il n'y a pas de débordement; toute opération qui produit une valeur en dehors de la plage du type s'enroule, par exemple UINT_MAX + 1U == 0U
.
Tout type entier, signé ou non, modélise une sous-plage 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 de 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 se produisent uniquement pour les 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 se produisent pour de très grandes valeurs positives et à zéro . Cela peut être une source de bugs. Par exemple, il s'agit d'une boucle infinie:
for (unsigned int i = 10; i >= 0; i --) [
printf("%u\n", i);
}
car i
est toujours supérieur ou égal à zéro; c'est la nature des types non signés. (À l'intérieur de la boucle, quand i
vaut zéro, i--
définit sa valeur sur UINT_MAX
.)
Parfois, nous savons à l'avance que la valeur stockée dans une variable entière donnée sera toujours positive - lorsqu'elle est utilisée pour ne compter que des choses, par exemple. Dans ce 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 autorisées (pour un compilateur 32 bits) passera de la plage -2147483648 à +2147483647 à la plage 0 à 4294967295. Ainsi, déclarer un entier non signé double presque la taille du plus grand possible valeur qu'il peut autrement tenir.
En termes simples, un entier non signé est un entier qui ne peut pas être négatif et a donc une plage de valeurs positives plus élevée qu'il peut supposer. Un entier signé est un entier qui peut être négatif mais qui a une plage positive inférieure en échange de valeurs plus négatives qu'il peut supposer.
En pratique, il existe deux différences:
cout
en C ++ ou printf
en C): la représentation de bits entiers non signés est interprétée comme un entier non négatif par les fonctions d'impression.ce code peut identifier l'entier en utilisant le critère de commande:
char a = 0;
a--;
if (0 < a)
printf("unsigned");
else
printf("signed");