En C / C ++, à quoi unsigned char
sert un? En quoi est-ce différent d'un habitué char
?
En C ++, il existe trois types de caractères distincts :
char
signed char
unsigned char
Si vous utilisez des types de caractères pour le texte , utilisez le non qualifié char
:
'a'
ou '0'
."abcde"
Il 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 à travers les inégalités - bien que si vous vous limitez à ASCII (0-127), vous êtes à peu près en sécurité.
Si vous utilisez des types de caractères sous forme de nombres , utilisez:
signed char
, ce qui vous donne au moins la gamme -127 à 127. (-128 à 127 est courant)unsigned char
, ce 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 1 (c'est-à-dire un octet), mais un octet pourrait en théorie être par exemple 32 bits. sizeof
serait toujours signaler sa taille comme1
- ce qui signifie que vous pourriez avoir sizeof (char) == sizeof (long) == 1
.
sizeof
car ce n'est pas une fonction mais un opérateur. Il est préférable de supprimer la parenthèse lors de la prise de la taille d'une variable.sizeof *p
ousizeof (int)
. Cela indique rapidement si elle s'applique à un type ou à une variable. De même, il est également redondant de mettre des parenthèses aprèsreturn
. Ce n'est pas une fonction.char
: c'est le type de littéraux de caractères comme'a'
ou'0'
." est vrai en C ++ mais pas en C. En C,'a'
est unint
.Cela dépend de l'implémentation, car la norme C ne définit PAS la signature de
char
. Selon la plate-forme, char peut êtresigned
orunsigned
, vous devez donc demander explicitementsigned char
ouunsigned char
si votre implémentation en dépend. Utilisez simplementchar
si vous avez l'intention de représenter des caractères à partir de chaînes, car cela correspondra à ce que votre plate-forme met dans la chaîne.La différence entre
signed char
etunsigned char
est comme vous vous en doutez. Sur la plupart des plates-formes,signed char
sera un nombre complémentaire de deux bits de 8 bits allant de-128
à127
, etunsigned char
sera un entier non signé de 8 bits (0
à255
). Notez que la norme n'exige PAS que leschar
types aient 8 bits, seulement cesizeof(char)
retour1
. Vous pouvez obtenir le nombre de bits dans un caractère avecCHAR_BIT
inlimits.h
. Il y a peu ou pas de plateformes aujourd'hui où ce sera autre chose que8
, cependant.Il y a un bon résumé de ce problème ici .
Comme d'autres l'ont mentionné depuis que j'ai posté cela, il vaut mieux utiliser
int8_t
etuint8_t
si vous voulez vraiment représenter de petits entiers.la source
CHAR_BIT
doit être d'au moins 8 bits selon la norme.Parce que je pense 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 de
unsigned char
participent à la détermination de la valeur d'un objet char non signé. Deuxièmement,unsigned char
est explicitement déclaré non signé.Maintenant, j'ai eu une discussion avec quelqu'un sur ce qui se passe lorsque vous convertissez la valeur
-1
de type int enunsigned char
. Il a refusé l'idée que le résultatunsigned char
ait tous ses bits mis à 1, car il était préoccupé par la représentation des signes. Mais il n'est pas obligé. C'est immédiatement après cette règle que la conversion fait ce qui est prévu:Voilà une description mathématique. C ++ le décrit en termes de calcul modulo, qui cède à la même règle. Quoi qu'il en soit, ce qui n'est pas garanti, c'est que tous les bits de l'entier
-1
sont un avant la conversion. Alors, qu'est-ce que nous avons pour que nous puissions prétendre que le résultatunsigned char
a tous sesCHAR_BIT
bits mis à 1?UCHAR_MAX+1
à-1
donnera une valeur dans la plage, à savoirUCHAR_MAX
Ça suffit, en fait! Donc, chaque fois que vous voulez en avoir un
unsigned char
, vous le faitesIl s'ensuit également qu'une conversion ne consiste pas seulement à tronquer des bits d'ordre supérieur. L'événement heureux pour le complément à deux est qu'il ne s'agit que d'une troncature, mais ce n'est pas nécessairement le cas pour les autres représentations de signes.
la source
UCHAR_MAX
?(unsigned type)-1
c'est une sorte d'idiome.~0
n'est pas.int x = 1234
etchar *y = &x
. Représentation binaire de1234
is00000000 00000000 00000100 11010010
. Ma machine est peu endienne donc elle l'inverse et stocker en mémoire11010010 00000100 00000000 00000000
LSB vient en premier. Maintenant partie principale. si j'utiliseprintf("%d" , *p)
.printf
lira premier octet11010010
que la sortie est ,-46
mais11010010
est210
alors pourquoi faut - il imprimer-46
. Je suis vraiment confus, je suppose que certains chars en promotion entière font quelque chose mais je ne sais pas.Comme par exemple les utilisations du caractère non signé :
unsigned char
est souvent utilisé en infographie, qui attribue très souvent (mais pas toujours) un seul octet à chaque composant de couleur. Il est courant de voir une couleur RGB (ou RGBA) représentée par 24 (ou 32) bits, chacun ununsigned char
. Étant donné que lesunsigned char
valeurs se situent dans la plage [0,255], les valeurs sont généralement interprétées comme:Vous vous retrouveriez donc avec du rouge RVB comme (255,0,0) -> (100% rouge, 0% vert, 0% bleu).
Pourquoi ne pas utiliser un
signed char
? Le décalage arithmétique et binaire devient problématique. Comme expliqué précédemment,signed char
la plage de a est essentiellement décalée de -128. Une méthode très simple et naïve (pour la plupart inutilisée) pour convertir le RVB en niveaux de gris consiste à faire la moyenne des trois composantes de couleur, mais cela pose des problèmes lorsque les valeurs des composantes de couleur sont négatives. Le rouge (255, 0, 0) fait la moyenne de (85, 85, 85) lors de l'utilisation de l'unsigned char
arithmétique. Cependant, si les valeurs étaientsigned char
s (127, -128, -128), nous nous retrouverions avec (-99, -99, -99), ce qui serait (29, 29, 29) dans notreunsigned char
espace, ce qui est incorrect .la source
Si vous souhaitez utiliser un caractère comme un petit entier, la façon la plus sûre de le faire est d'utiliser les types
int8_t
etuint8_t
.la source
int8_t
etuint8_t
sont facultatives et ne sont pas définis sur des architectures où la taille des octets ne sont pas exactement 8 bits. Inversement,signed char
etunsigned char
sont toujours disponibles et garantis pour contenir au moins 8 bits. C'est peut-être un moyen courant mais pas le plus sûr .signed char
etunsigned char
? Ou recommanderiez-vous une meilleure alternative "plus sûre" dans ce cas particulier? Par exemple, pour s'en tenir aux types entiers "réels"signed int
et à launsigned int
place pour une raison quelconque?signed char
etunsigned char
est portable pour toutes les implémentations conformes et économisera de l'espace de stockage mais peut entraîner une augmentation de la taille du code. Dans certains cas, on économiserait plus d'espace de stockage en stockant de petites valeurs dans des champs binaires ou des bits simples de types entiers réguliers. Il n'y a pas de réponse absolue à cette question, la pertinence de cette approche dépend du cas d'espèce. Et cette réponse ne répond pas de toute façon à la question.unsigned char
prend uniquement des valeurs positives ... comme 0 à 255tandis que
signed char
prend des valeurs positives et négatives ... comme -128 à +127la source
char
etunsigned char
ne sont pas garantis comme étant de type 8 bits sur toutes les plates-formes - ils sont garantis comme étant de 8 bits ou plus. Certaines plates-formes ont des octets 9 bits, 32 bits ou 64 bits . Cependant, les plates-formes les plus courantes aujourd'hui (Windows, Mac, Linux x86, etc.) ont des octets 8 bits.la source
signed char
a une plage de -128 à 127;unsigned char
a une plage de 0 à 255.char
sera équivalent à char signé ou 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 pour la portabilité.la source
An
unsigned char
est une valeur d'octet non signée (0 à 255). Vous pensez peut-êtrechar
en termes d'être un "personnage" mais c'est vraiment une valeur numérique. Le régulierchar
est signé, vous avez donc 128 valeurs, et ces valeurs sont mappées à des caractères à l'aide du codage ASCII. Mais dans les deux cas, ce que vous stockez en mémoire est une valeur d'octet.la source
En termes de valeurs directes, un caractère normal est utilisé lorsque les valeurs sont comprises entre
CHAR_MIN
etCHAR_MAX
tandis qu'un caractère non signé fournit le double de la plage à l'extrémité positive. Par exemple, si la valeurCHAR_BIT
est 8, la plage de valeurs régulièreschar
est uniquement garantie d'être [0, 127] (car elle peut être signée ou non) tandis queunsigned char
sera [0, 255] etsigned char
sera [-127, 127].En termes d'utilisation, les normes permettent aux objets de POD (données anciennes simples) d'être directement convertis en un tableau de caractères non signés. Cela vous permet d'examiner la représentation et les motifs binaires de l'objet. La même garantie de punition de type sûre n'existe pas pour le caractère ou le caractère signé.
la source
unsigned char
, pas un tableau en particulier, et toute "conversion" n'est définie formellement qu'en copiant de l'objet vers un véritable tableau déclaré deunsigned char
& inspectant ensuite ce dernier. Il n'est pas clair si le OU peut être directement réinterprété comme un tel tableau, avec les tolérances pour l'arithmétique du pointeur qu'il impliquerait, c'est-à-dire si "séquence"==
"tableau" dans cette utilisation. Il y a un problème principal n ° 1701 dans l'espoir de clarifier cela. Heureusement, car cette ambiguïté me dérange vraiment récemment.unsigned char
du bloc++ptr
opératoire, puis continuer à utiliser à partir de là pour en lire chaque octet ... mais AFAICT, ce n'est pas spécifiquement défini comme étant autorisé, donc nous sommes laissé à déduire que c'est «probablement OK» de nombreux autres passages (et à bien des égards, la simple existence dememcpy
) dans la norme, semblable à un puzzle. Ce qui n'est pas idéal. Eh bien, peut-être que le libellé s'améliorera éventuellement. Voici le problème CWG que j'ai mentionné mais qui manquait d'espace pour créer ununsigned char
est le cœur de la supercherie. Dans presque TOUS les compilateurs pour TOUTES les plateformes, ununsigned char
est simplement un octet et 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 char. de sorte que vous avez 3 différents
char
types:char
,signed char
,unsigned char
.la source
Si vous aimez en utilisant différents types de longueur spécifique et signedness, vous êtes probablement mieux avec
uint8_t
,int8_t
,uint16_t
, etc simplement parce qu'ils font exactement ce qu'ils disent.la source
Certains googleurs ont trouvé cela , où les gens ont eu une discussion à ce sujet.
Un caractère non signé est essentiellement un octet unique. Donc, vous l'utiliseriez si vous avez besoin d'un octet de données (par exemple, vous souhaitez peut-être l'utiliser pour activer et désactiver les indicateurs à transmettre à une fonction, comme cela se fait souvent dans l'API Windows).
la source
Un caractère non signé utilise le bit réservé au signe d'un caractère normal comme un autre nombre. Cela change 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 lorsque vous faites des choses comme le décalage des bits (décalage étend le signe) et d'autres choses lorsque vous traitez un caractère comme un octet plutôt que de l'utiliser comme un nombre.
la source
unsigned char
prend uniquement des valeurs positives: 0 à 255 tandis quesigned char
prend des valeurs positives et négatives: -128 à +127.la source
cité à partir du livre "le c programmation laugage":
Le qualificatif
signed
ouunsigned
peut être appliqué à char ou à n'importe quel entier. les nombres non signés sont toujours positifs ou nuls et obéissent aux lois du module arithmétique 2 ^ n, où n est le nombre de bits du type. Ainsi, par exemple, si les caractères sont de 8 bits, les variables de caractères non signés 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 complémentaire à deux). -dépendant, mais les caractères imprimables sont toujours positifs.la source
signed char
et lesunsigned char
deux représentent 1 octet, mais ils ont des plages différentes.Dans
signed char
si nous considéronschar letter = 'A'
, 'A' est un binaire de 65 poucesASCII/Unicode
, si 65 peut être stocké, -65 peut également être stocké. Il n'y a pas de valeurs binaires négativesASCII/Unicode
là-dedans sans avoir à se soucier des valeurs négatives.Exemple
Production -:
la source