Quelle est la différence entre un entier signé et non signé

91

Quelle est la différence entre les entiers signés et non signés?

Moumita Das
la source
5
C'est une vraie question, et la réponse n'est pas si simple mais plutôt subtile.
R .. GitHub STOP HELPING ICE
Voter pour rouvrir. C'est peut-être un double, mais c'est définitivement une vraie question.
Brian
4
Re: "Cela pourrait être un doublon" - Quelle est la différence entre unsigned int et signed int en C?
eldarerathis
D'autres balises devraient être ajoutées, car de nombreuses langues les utilisent.
Juan Boero
Cette question peut nécessiter un chapitre à élaborer. Si vous voulez connaître les tenants et les aboutissants, cochez les entiers non signés et signés pour plus d'explications.
anonyme

Réponses:

113

Comme vous le savez probablement, les ints sont stockés en interne en binaire. En général, un intcontient 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 intou 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 ints, le bit le plus significatif est 1si et seulement si le nombre est négatif. C'est pourquoi, pour signed ints, ce bit est appelé "bit de signe".

Bill Evans chez Mariposa
la source
11
Il convient peut-être de souligner qu'il s'agit du format du complément à deux, qui est certes largement utilisé de nos jours. Il existe également d'autres façons de représenter des entiers signés, notamment son complément.
Schedler
Correct. Et la norme ISO9899 C n'exige même pas l'utilisation d'un complément à un ou à deux; toute autre convention qui fonctionne réellement est autorisée.
Bill Evans à Mariposa le
1
Bien que le complément à deux ne soit pas requis, il (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.
rubenvb
3
@BillEvansatMariposa: La norme dit que pour les entiers signés, il y a 3 représentations autorisées: signe + magnitude, complément à 2, complément à 1. Tout autre devrait être invisible pour le programme et être perçu comme l'un de ces 3.
Alexey Frunze
Ok mais sous le capot! Qu'est-ce qui se passe VRAIMENT! Quelle est la différence entre un numéro SIGNÉ et NON SIGNÉ! Comment la machine gère-t-elle le calcul? Il soustrait juste une valeur de l'autre? Comment ça diffère 1111 = 15 et 1111 = -1?
Mihail Georgescu
19

intet unsigned intsont deux types d'entiers distincts. ( intpeut également être appelé signed int, ou simplementsigned ; unsigned intpeut également être appelé unsigned.)

Comme les noms l'impliquent, intest un type entier signé , et unsigned intest un non signé type entier . Cela signifie qu'il intpeut représenter des valeurs négatives et unsigned intne peut représenter que des valeurs non négatives.

Le langage C impose certaines exigences sur les plages de ces types. La plage de intdoit être d'au moins -32767.. +32767et la plage de unsigned intdoit ê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. inta 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_MINet 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 iest toujours supérieur ou égal à zéro; c'est la nature des types non signés. (À l'intérieur de la boucle, quand ivaut zéro, i--définit sa valeur sur UINT_MAX.)

Keith Thompson
la source
12

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.

Imran
la source
@Alex J'étais en train d'éditer cette réponse il y a 10 minutes et c'est identique. lol
Skuld
12

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.

user2977636
la source
0

En pratique, il existe deux différences:

  1. impression (par exemple avec couten C ++ ou printfen 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.
  2. commande : la commande dépend d'une spécification signée ou non signée.

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");
Minimus Heximus
la source
Si cela expliquait la différence avec l'un traitant des nombres négatifs et l'autre, non. Cela aiderait beaucoup ce message.
Daniel Jackson
@DanielJackson Vous ne savez pas ce que vous dites. un caractère peut être considéré comme négatif ou positif selon le compilateur. la sortie du code dépend de ce que le compilateur choisit et cela montre la différence entre signé et non signé.
Minimus Heximus