web-dev-qa-db-fra.com

Qu'est-ce qu'un personnage non signé?

En C/C++, à quoi sert un unsigned char? En quoi est-il différent d'un char normal?

440
Landon Kuhn

En C++, il existe trois types de caractère distincts :

  • char
  • _signed char_
  • _unsigned char_

Si vous utilisez des types de caractères pour le texte , utilisez l'option char non qualifiée:

  • il s'agit du type de littéraux de caractères tels que _'a'_ ou _'0'_.
  • c'est le type qui compose les chaînes C comme _"abcde"_

Cela fonctionne également comme une valeur numérique, mais il n'est pas spécifié si cette valeur est traitée comme signée ou non signée. Méfiez-vous des comparaisons de caractères par le biais d'inégalités - bien que si vous vous limitez à ASCII (0-127), vous êtes sur le point de ne pas risque.

Si vous utilisez des types de caractères sous forme de nombres , utilisez:

  • _signed char_, qui vous donne au moins la plage de -127 à 127. (-128 à 127 est commun)
  • _unsigned char_, qui vous donne au moins la plage de 0 à 255.

"Au moins", car la norme C++ ne donne que la plage minimale de valeurs que chaque type numérique doit couvrir. sizeof (char) doit être égal à 1 (c'est-à-dire un octet), mais un octet pourrait théoriquement être par exemple 32 bits. sizeof RAPPORTERA TOUJOURS SA TAILLE SOUS LA FORME _1 - ce qui signifie que vous pourriez avoir sizeof (char) == sizeof (long) == 1.

520
Fruny

Cela dépend de la mise en œuvre, car le standard C NE définit PAS la signature de char. Selon la plate-forme, char peut être signed ou unsigned, vous devez donc demander explicitement signed char ou unsigned char si votre implémentation en dépend. Utilisez simplement char si vous souhaitez représenter des caractères à partir de chaînes, car cela correspond à ce que votre plate-forme place dans la chaîne.

La différence entre signed char et unsigned char est conforme à vos attentes. Sur la plupart des plates-formes, signed char sera un numéro de complément à 8 bits allant de -128 à 127, et unsigned char sera un entier non signé de 8 bits (0 à 255). Notez que la norme n'exige PAS que les types char aient 8 bits, uniquement que sizeof(char) renvoie 1. Vous pouvez obtenir le nombre de bits d'un caractère avec CHAR_BIT dans limits.h. Cependant, il existe peu ou pas de plates-formes où ce sera autre chose que 8.

Il existe un bon résumé de ce problème ici .

Comme d'autres l'ont mentionné depuis que j'ai posté ceci, vous feriez mieux d'utiliser int8_t et uint8_t si vous voulez vraiment représenter de petits entiers.

83
Todd Gamblin

Parce que j'estime que c'est vraiment nécessaire, je veux juste énoncer quelques règles de C et C++ (elles sont les mêmes à cet égard). Tout d'abord, tous les bits sur unsigned char participe à la détermination de la valeur, le cas échéant, de l'objet char non signé. Deuxièmement, unsigned char est explicitement déclaré non signé.

Maintenant, j'ai discuté avec quelqu'un de ce qui se passe lorsque vous convertissez la valeur -1 de type int en unsigned char. Il a refusé l'idée que tous les bits du unsigned char résultant soient définis sur 1, car il craignait la représentation des signes. Mais il n'est pas obligé. En suivant immédiatement cette règle, la conversion fait ce qui est prévu:

Si le nouveau type n'est pas signé, la valeur est convertie en ajoutant ou en soustrayant de manière répétée une valeur de plus que la valeur maximale pouvant être représentée dans le nouveau type jusqu'à ce que la valeur se situe dans la plage du nouveau type. (6.3.1.3p2 dans un brouillon C99)

C'est une description mathématique. C++ le décrit en termes de modulo calcul, qui obéit à la même règle. Quoi qu'il en soit, ce qui est non garanti, c'est que tous les bits du nombre entier -1 sont égaux à un avant la conversion. Alors, qu'est-ce que nous avons pour pouvoir prétendre que le unsigned char résultant a tous ses CHAR_BIT bits devenus 1?

  1. Tous les bits participent à la détermination de sa valeur, c'est-à-dire qu'aucun bit de remplissage ne se produit dans l'objet.
  2. L'ajout d'une seule fois UCHAR_MAX+1 à -1 donnera une valeur dans la plage, à savoir UCHAR_MAX

C'est assez, en fait! Donc, chaque fois que vous voulez avoir un unsigned char ayant tous ses bits un, vous faites

unsigned char c = (unsigned char)-1;

Il s'ensuit également qu'une conversion ne fait que pas simplement tronquer les bits de poids fort. L'événement chanceux pour complément à deux est qu'il ne s'agit que d'une troncature, mais que ce n'est pas nécessairement le cas pour les autres représentations de signe.

34

Comme par exemple les utilisations de nsigned char:

nsigned char est souvent utilisé en infographie, qui attribue très souvent (mais pas toujours) un octet à chaque composant couleur. Il est courant de voir une couleur RVB (ou RVBA) représentée par 24 (ou 32) bits, chacun un caractère non signé. Puisque les valeurs nsigned char se situent dans la plage [0,255], elles sont généralement interprétées comme suit:

  • 0 signifie l'absence totale d'une composante de couleur donnée.
  • 255 signifiant 100% d'un pigment de couleur donné.

Ainsi, vous obtiendrez un rouge RVB tel que (255,0,0) -> (100% rouge, 0% vert, 0% bleu).

Pourquoi ne pas utiliser un caractère signé? L'arithmétique et le transfert de bits deviennent problématiques. Comme expliqué précédemment, la plage de signée est essentiellement décalée de -128. Une méthode très simple et naïve (la plupart du temps inutilisée) pour convertir RVB en niveaux de gris consiste à faire la moyenne des trois composantes de couleur, mais cela peut poser problème lorsque les valeurs des composantes de couleur sont négatives. Le rouge (255, 0, 0) fait la moyenne de (85, 85, 85) lorsque caractère non signé arithmétique. Cependant, si les valeurs étaient caractère signé s (127, -128, -128), nous nous retrouverions avec (-99, -99, -99), ce qui serait (29, 29, 29) dans notre nsigned char space, ce qui est incorrect.

24
Zachary Garrett

Si vous souhaitez utiliser un caractère sous forme de petit nombre entier, le moyen le plus sûr consiste à utiliser les types int8_tet uint8_t.

12
jbleners

unsigned char ne prend que des valeurs positives .... comme à 255

tandis que

signed char prend les valeurs positives et négatives .... comme - 128 à + 127

6
munna

char et unsigned char ne sont pas garantis en tant que types 8 bits sur toutes les plates-formes; ils sont garantis au moins en 8 bits. Certaines plates-formes ont octets 9 bits, 32 bits ou 64 bits . Cependant, les plates-formes les plus courantes à l'heure actuelle (Windows, Mac, Linux x86, etc.) ont des octets de 8 bits.

6
bk1e

signed char est compris entre -128 et 127; unsigned char est compris entre 0 et 255.

char sera équivalent à char signé ou à char non signé, selon le compilateur, mais est un type distinct.

Si vous utilisez des chaînes de style C, utilisez simplement char. Si vous devez utiliser des caractères pour l'arithmétique (assez rare), spécifiez explicitement signé ou non signé pour la portabilité.

5
James Hopkin

Un caractère non signé est une valeur d'octet (non signé) (0 à 255). Vous pensez peut-être que "caractère" est un "caractère", mais il s’agit vraiment d’une valeur numérique. Le "caractère" normal est signé. Vous disposez donc de 128 valeurs. Ces valeurs sont mappées sur des caractères utilisant le codage ASCII. Mais dans les deux cas, ce que vous stockez en mémoire est une valeur d'octet.

4
Zac Gochenour

En termes de valeurs directes, un caractère normal est utilisé lorsque les valeurs sont comprises entre CHAR_MIN et CHAR_MAX, tandis qu'un caractère non signé fournit le double de la plage de l'extrémité positive. Par exemple, si CHAR_BIT vaut 8, la plage de char normale est uniquement garantie de [0, 127] (car elle peut être signée ou non signée), tandis que unsigned char sera [0. , 255] et signed char sera [-127, 127].

En termes d’utilisation, les normes permettent aux objets de POD (plain old data) d’être convertis directement en un tableau de caractères non signés. Cela vous permet d'examiner la représentation et les modèles de bits de l'objet. La même garantie de sécurisation du type n'existe pas pour char ou char signé.

4
Julienne Walker

Si vous aimez utiliser différents types de longueur et de signature spécifiques, vous êtes probablement mieux avec uint8_t, int8_t, uint16_t, etc. simplement parce qu'ils font exactement ce qu'ils disent.

2
Dark Shikari

Un caractère non signé utilise le bit réservé au signe d'un caractère normal comme un autre nombre. Cela modifie la plage en [0 - 255] par opposition à [-128 - 127].

Généralement, les caractères non signés sont utilisés lorsque vous ne voulez pas de signe. Cela fera une différence lorsqu’il s’agira de déplacer des bits (shift étend le signe) et d’autres choses lorsqu’il s’agit d’un caractère sous forme d’octet plutôt que de l’utiliser sous forme de nombre.

2
JasonOfEarth

un caractère non signé est le cœur de toute tromperie. Dans presque tous les compilateurs pour toutes les plateformes, un caractère non signé est simplement un BYTE. Un entier non signé de (généralement) 8 bits. qui peut être traité comme un petit entier ou un paquet de bits.

En dépendance, comme quelqu'un l'a dit, la norme ne définit pas le signe d'un caractère. vous avez donc 3 types de "char" distincts: char, char signé, char non signé.

2
ugasoft

Un certain Google a trouvé ceci , où les gens ont eu une discussion à ce sujet.

Un caractère non signé est fondamentalement un seul octet. Donc, vous utiliseriez ceci si vous avez besoin d'un octet de données (par exemple, vous pouvez l'utiliser pour définir des indicateurs à transmettre à une fonction, comme cela est souvent le cas dans l'API Windows).

1
dbrien

unsigned char prend uniquement des valeurs positives: 0 à 255 signé car prend des valeurs positives et négatives: -128 à +127

0
NL628

cité dans le livre "the c programming laugage":

Le qualificatif signed ou unsigned peut être appliqué à char ou à tout entier. les nombres non signés sont toujours positifs ou nuls et respectent les lois de l'arithmétique modulo 2 ^ n, où n est le nombre de bits du type. Ainsi, par exemple, si les caractères sont de 8 bits, les variables non signées ont des valeurs comprises entre 0 et 255, tandis que les caractères signés ont des valeurs comprises entre -128 et 127 (dans une machine du complément à deux). Indique si les caractères simples sont signés ou non signés -dépendant, mais les caractères imprimables sont toujours positifs.

0
ZhaoGang