Ai-je raison de dire que la différence entre un entier signé et non signé est la suivante:
Y a-t-il d'autres différences?
Unsigned peut contenir une valeur positive plus grande et aucune valeur négative.
Oui.
Unsigned utilise le bit de premier plan comme partie de la valeur, tandis que la version signée utilise le bit le plus à gauche pour identifier si le nombre est positif ou négatif.
Il existe différentes manières de représenter des entiers signés. Le plus facile à visualiser consiste à utiliser le bit le plus à gauche comme indicateur ( signe et magnitude ), mais le plus commun est complément à deux . Les deux sont utilisés dans la plupart des microprocesseurs modernes - la virgule flottante utilise le signe et la magnitude, tandis que l'arithmétique entière utilise le complément à deux.
les entiers signés peuvent contenir des nombres positifs et négatifs.
Oui
Je vais aller dans les différences au niveau du matériel, sur x86. Cela est généralement sans importance sauf si vous écrivez un compilateur ou utilisez le langage Assembly. Mais c'est bon à savoir.
Premièrement, x86 supporte en natif la représentation complément à deux des nombres signés. Vous pouvez utiliser d'autres représentations, mais cela nécessiterait davantage d'instructions et constituerait généralement une perte de temps de traitement.
Qu'est-ce que je veux dire par "support natif"? En gros, je veux dire que vous utilisez un ensemble d'instructions pour les numéros non signés et un autre ensemble que vous utilisez pour les numéros signés. Les numéros non signés peuvent figurer dans les mêmes registres que les numéros signés. Vous pouvez ainsi combiner des instructions signées et non signées sans vous inquiéter pour le processeur. Il appartient au compilateur (ou au programmeur de l’Assemblée) de savoir si un numéro est signé ou non, et d’utiliser les instructions appropriées.
Premièrement, les nombres complémentaires à deux ont la propriété que l'addition et la soustraction sont identiques aux nombres non signés. Que les chiffres soient positifs ou négatifs ne fait aucune différence. (Donc, il vous suffit d'aller de l'avant et ADD
et SUB
vos chiffres sans souci.)
Les différences commencent à montrer quand il s'agit de comparaisons. x86 a un moyen simple de les différencier: haut/bas indique une comparaison non signée et supérieur/inférieur à une comparaison signée. (Exemple: JAE
signifie "Saute si supérieur ou égal" et n'est pas signé.)
Il existe également deux ensembles d'instructions de multiplication et de division pour traiter les entiers signés et non signés.
Enfin, si vous souhaitez vérifier, par exemple, un débordement, vous le feriez différemment pour les numéros signés et non signés.
Il a seulement demandé à propos de signé et non signé. Je ne sais pas pourquoi les gens ajoutent des trucs supplémentaires à ça. Laissez-moi vous dire la réponse.
Non signé: Il ne contient que des valeurs non négatives, à savoir 0 à 255.
Signé: Il se compose de valeurs négatives et positives mais dans différents formats comme
Et cette explication concerne le système de numérotation à 8 bits.
Quelques points à compléter:
cette réponse ne traite que des représentations entières. Il peut y avoir d'autres réponses pour virgule flottante;
la représentation d'un nombre négatif peut varier. Le plus commun (de loin - il est presque universel aujourd'hui) utilisé aujourd'hui est complément à deux. Les autres représentations incluent complément (assez rare) et magnitude signée (extrêmement rare - probablement utilisé uniquement pour les pièces de musée), qui utilise simplement le bit haut comme indicateur de signe avec le restent des bits représentant la valeur absolue du nombre.
Lorsque vous utilisez le complément à deux, la variable peut représenter un plus grand nombre (de un) de nombres négatifs que de nombres positifs. Cela est dû au fait que zéro est inclus dans les nombres "positifs" (puisque le bit de signe n'est pas défini pour zéro), mais pas les nombres négatifs. Cela signifie que la valeur absolue du plus petit nombre négatif ne peut pas être représentée.
lorsque vous utilisez son complément ou sa magnitude signée, vous pouvez avoir le zéro représenté sous forme de nombre positif ou négatif (ce qui est l'une des raisons pour lesquelles ces représentations ne sont généralement pas utilisées).
Selon ce que nous avons appris en classe, les entiers signés peuvent représenter à la fois des nombres positifs et négatifs, tandis que les entiers non signés ne sont que non négatif.
Par exemple, en regardant un nombre 8 bits:
unsigned valeurs 0
à 255
signé les valeurs vont de -128
à 127
Tout sauf le point 2 est correct. Il existe de nombreuses notations différentes pour les ints signés, certaines implémentations utilisent la première, d'autres la dernière et d'autres encore utilisent quelque chose de complètement différent. Tout dépend de la plateforme sur laquelle vous travaillez.
Une autre différence réside dans la conversion entre des entiers de tailles différentes.
Par exemple, si vous extrayez un entier d'un flux d'octets (par exemple, 16 bits par souci de simplicité), avec des valeurs non signées, vous pouvez effectuer les opérations suivantes:
i = ((int) b[j]) << 8 | b[j+1]
(devrait probablement jeter le 2dakota du Nord octet, mais je suppose que le compilateur fera le bon choix)
Avec les valeurs signées, vous devez vous préoccuper de l’extension de signe et faire:
i = (((int) b[i]) & 0xFF) << 8 | ((int) b[i+1]) & 0xFF
De manière générale, c'est correct. Sans en savoir plus sur les raisons pour lesquelles vous recherchez des différences, je ne vois aucun autre différenciateur entre signé et non signé.
(en réponse à la deuxième question) En utilisant uniquement un bit de signe (et non un complément à 2), vous pouvez vous retrouver avec -0. Pas très jolie.
Au-delà de ce que d'autres ont dit, en C, vous ne pouvez pas déborder d'un entier non signé; le comportement est défini comme étant un module arithmétique. Vous pouvez déborder d'un nombre entier signé et, en théorie (bien que ce ne soit pas le cas sur les systèmes traditionnels actuels), le débordement pourrait provoquer une erreur (similaire à une division par zéro).
Les entiers non signés sont beaucoup plus susceptibles de vous prendre dans un piège que les entiers signés. Le piège vient du fait que, bien que 1 et 3 ci-dessus soient corrects, les deux types d’entiers peuvent être assignés une valeur en dehors des limites de ce qu’elle peut "contenir" et il sera converti en silence.
unsigned int ui = -1;
signed int si = -1;
if (ui < 0) {
printf("unsigned < 0\n");
}
if (si < 0) {
printf("signed < 0\n");
}
if (ui == si) {
printf("%d == %d\n", ui, si);
printf("%ud == %ud\n", ui, si);
}
Lorsque vous exécutez cette opération, vous obtenez le résultat suivant même si les deux valeurs ont été affectées à -1 et ont été déclarées différemment.
signed < 0
-1 == -1
4294967295d == 4294967295d
Les entiers signés en C représentent des nombres. Si a
et b
sont des variables de types entiers signés, la norme ne demandera jamais à un compilateur de mémoriser l'expression a+=b
dans a
autre que la somme arithmétique de leurs valeurs respectives. Pour être sûr, si la somme arithmétique ne rentre pas dans a
, le processeur pourrait ne pourra pas le mettre ici, mais la norme ne nécessiterait pas que le compilateur tronque ou encapsule la valeur , ou faire n'importe quoi d'autre d'ailleurs si les valeurs dépassent les limites pour leurs types. Notez que, bien que la norme ne l'exige pas, les implémentations C sont autorisées à intercepter les dépassements arithmétiques avec des valeurs signées.
Les entiers non signés en C se comportent comme des anneaux algébriques abstraits d'entiers congruents modulo une puissance égale à deux, sauf dans les scénarios impliquant des conversions ou des opérations avec des types plus volumineux. La conversion d'un entier de n'importe lequel taille en un type non signé de 32 bits donnera le membre correspondant aux choses qui sont congruentes à cet entier, mod 4,294,967,296. La raison pour laquelle on soustrait 3 de 2 donne 4 294 967 295, c’est que le fait d’ajouter un élément congru de 3 à 4 294 967 295 donne un résultat congru de 2.
Les types d’anneaux algébriques abstraits sont souvent utiles; Malheureusement, C utilise la signature comme facteur décisif pour déterminer si un type doit se comporter comme un anneau. Pire encore, les valeurs non signées sont traitées comme des nombres plutôt que des membres de l'anneau lors de la conversion en types plus grands, et les valeurs non signées inférieures à int
sont converties en nombres lorsqu'une opération arithmétique est effectuée sur elles. Si v
est un uint32_t
égal à 4,294,967,294
, alors v*=v;
doit produire v=4
. Malheureusement, si int
est de 64 bits, rien ne dit ce que v*=v;
pourrait faire.
Compte tenu de la norme telle qu'elle est, je suggérerais d'utiliser des types non signés dans des situations où l'on souhaite le comportement associé aux anneaux algébriques et des types signés lorsque l'on veut représenter des nombres. Il est regrettable que C ait établi les distinctions de cette manière, mais elles sont ce qu’elles sont.
Vous devez utiliser des entiers non signés lors de la programmation sur des systèmes intégrés. Dans les boucles, lorsqu'il n'est pas nécessaire d'utiliser des entiers signés, l'utilisation d'entiers non signés économisera les sauvegardes nécessaires à la conception de tels systèmes.
La seule différence garantie entre une valeur signée et une valeur non signée en C est que la valeur signée peut être négative, 0 ou positive, tandis qu'un non signé ne peut être que 0 ou positif. Le problème est que C ne définit pas le format des types (donc savoir que vos entiers sont dans le complément à deux). Strictement parlant, les deux premiers points que vous avez mentionnés sont incorrects.