Le seul ouvrage de référence en C auquel je fais confiance est "C: A Reference Manual" de Harbison & Steele ( careencemanual.com ). Bien sûr, la norme est le dernier mot, mais elle n'est pas très lisible et ne donne que la moindre information sur les utilisations pré-standard et courantes (c'est-à-dire POSIX) qui sont en dehors de la norme. Harbison & Steele est assez lisible, détaillé et probablement plus correct que la plupart des références. Cependant, ce n'est pas non plus un tutoriel, donc si vous êtes dans les premières étapes de l'apprentissage, ce n'est probablement pas une bonne chose à faire.
Michael Burr
15
Je pense que le livre que vous lisez est C: The Complete Reference , par Herbert Schildt. D'après une critique de ce livre ( accu.informika.ru/accu/bookreviews/public/reviews/c/c002173.htm ): Je ne recommanderai pas ce livre (trop d'entre vous accordent trop d'importance à mes opinions) mais Je ne pense pas qu'il mérite le même opprobre qui a été légitimement jeté à certains de ses autres travaux. Comme Michael le dit, une bien meilleure référence est Harbison & Steele .
Alok Singhal
Mes deux cents ici: Parce que charpeut être non signé, en règle générale, utilisez un intpour lire une valeur en utilisant getchar(), qui pourrait retourner EOF. EOFest généralement défini comme -1ou une autre valeur négative, dont le stockage dans un unsignedn'est pas ce que vous voulez. Voici la déclaration: extern int getchar();BTW, cette recommandation vient également du livre "C: A Reference Manual".
Maxim Chetrusca
6
La seule référence C en laquelle j'ai confiance est ISO / IEC 9899: 2011 :-)
Jeff
3
@MaxChetrusca Bon conseil mais mauvaise justification: même sur le charcas signé , il faudrait l'utiliser intpour stocker la valeur de retour.
Antti Haapala
Réponses:
204
Le livre est faux. La norme ne spécifie pas si plain charest signé ou non signé.
En fait, la norme définit trois types distincts: char, signed charet unsigned char. Si vous #include <limits.h>regardez ensuite CHAR_MIN, vous pouvez savoir si plain charest signedou unsigned(si CHAR_MINest inférieur à 0 ou égal à 0), mais même dans ce cas, les trois types sont distincts en ce qui concerne la norme.
Notez que charc'est spécial de cette manière. Si vous déclarez une variable car intelle équivaut à 100% à la déclarer comme signed int. Ceci est toujours vrai pour tous les compilateurs et architectures.
@Alok: la même chose n'est pas vraie pour certains autres types de données, par exemple intsignifie signed inttoujours, non? À part char, dans quels autres types de données ont la même confusion C?
Lazer
8
@eSKay: oui, charc'est le seul type qui peut être signé ou non signé. intéquivaut à signed intpar exemple.
Alok Singhal
28
Il y a une raison hystérique, euh, historique à cela - au début de la vie de C, le «standard» a été inversé au moins deux fois, et certains compilateurs populaires tôt ont fini dans un sens et d'autres dans l'autre.
Hot Licks
9
@AlokSinghal: Il est également défini par l'implémentation si un champ de bits de type intest signé ou non signé.
Keith Thompson
@KeithThompson merci pour la correction. J'ai tendance à oublier certains détails sur les types de champs de bits car je ne les utilise pas beaucoup.
Alok Singhal
67
Comme le souligne Alok , la norme laisse cela à la mise en œuvre.
Pour gcc, la valeur par défaut est signée, mais vous pouvez la modifier avec -funsigned-char. remarque: pour gcc dans Android NDK, la valeur par défaut est non signée . Vous pouvez également demander explicitement des caractères signés avec -fsigned-char.
Sur MSVC, la valeur par défaut est signée mais vous pouvez la modifier avec /J.
Il est intéressant de noter que la description de Schildt ne correspond pas au comportement de MSVC puisque ses livres sont généralement destinés aux utilisateurs de MSVC. Je me demande si MS a changé la valeur par défaut à un moment donné?
Michael Burr
1
Je pensais que cela ne dépendait pas du compilateur, mais de la plate-forme. Je pensais que char était laissé comme troisième type de "type de données de caractère" pour se conformer à ce que les systèmes à l'époque utilisaient comme caractères imprimables.
Spidey
10
La documentation GCC dit que cela dépend de la machine: " Chaque type de machine a une valeur par défaut pour ce que doit être le caractère. C'est soit comme un caractère non signé par défaut ou comme un caractère signé par défaut. "
Deduplicator
1
Pouvez-vous s'il vous plaît fournir une source pour votre note que sur Android, la valeur par défaut est un caractère non signé?
phlipsy
1
@Spidey le standard C ne fait aucune distinction réelle entre les compilateurs, les plates-formes et les architectures CPU. Il les regroupe simplement sous «mise en œuvre».
plugwash
35
C99 N1256 draft 6.2.5 / 15 "Types" a ceci à dire à propos de la signature du type char:
La mise en œuvre doit définir char pour avoir la même plage, la même représentation et le même comportement que char signé ou char non signé.
et dans une note de bas de page:
CHAR_MIN, défini dans <limits.h>, aura l'une des valeurs 0ou SCHAR_MIN, et cela peut être utilisé pour distinguer les deux options. Quel que soit le choix effectué, charest un type distinct des deux autres et n'est pas compatible avec l'un ou l'autre.
Selon le livre The C Programming Language de Dennis Ritchie, qui est le livre standard de facto pour ANSI C, les caractères simples signés ou non signés dépendent de la machine, mais les caractères imprimables sont toujours positifs.
Ce n'est pas nécessairement le cas que les caractères imprimables soient toujours positifs. La norme C garantit que tous les membres du jeu de caractères d'exécution de base ont des valeurs non négatives.
Keith Thompson
7
Selon la norme C, la signature de plain char est "définie par l'implémentation".
En général, les implémenteurs ont choisi celui qui était le plus efficace à implémenter sur leur architecture. Sur les systèmes x86, le caractère est généralement signé. Sur les systèmes armés, il n'est généralement pas signé (Apple iOS est une exception).
@plugwash Votre réponse a probablement été rejetée parce que Tim Post a perdu ses clés . Sérieusement cependant, vous ne devriez pas vous soucier d'un seul vote défavorable tant que vous êtes sûr que votre réponse est correcte (ce qui est le cas dans ce cas). Il m'est arrivé plusieurs fois de voir mes messages déclassés sans raison valable. Ne vous en faites pas, parfois les gens font des choses bizarres.
Donald Duck
1
Pourquoi le caractère signé est-il plus efficace sur x86? Des sources?
martinkunev
2
Selon «Le langage de programmation C ++» de Bjarne Stroustrup, char«l'implémentation est définie». Cela peut être signed charou unsigned charselon la mise en œuvre. Vous pouvez vérifier s'il charest signé ou non en utilisant std::numeric_limits<char>::is_signed.
char
peut être non signé, en règle générale, utilisez unint
pour lire une valeur en utilisantgetchar()
, qui pourrait retournerEOF
.EOF
est généralement défini comme-1
ou une autre valeur négative, dont le stockage dans ununsigned
n'est pas ce que vous voulez. Voici la déclaration:extern int getchar();
BTW, cette recommandation vient également du livre "C: A Reference Manual".char
cas signé , il faudrait l'utiliserint
pour stocker la valeur de retour.Réponses:
Le livre est faux. La norme ne spécifie pas si plain
char
est signé ou non signé.En fait, la norme définit trois types distincts:
char
,signed char
etunsigned char
. Si vous#include <limits.h>
regardez ensuiteCHAR_MIN
, vous pouvez savoir si plainchar
estsigned
ouunsigned
(siCHAR_MIN
est inférieur à 0 ou égal à 0), mais même dans ce cas, les trois types sont distincts en ce qui concerne la norme.Notez que
char
c'est spécial de cette manière. Si vous déclarez une variable carint
elle équivaut à 100% à la déclarer commesigned int
. Ceci est toujours vrai pour tous les compilateurs et architectures.la source
int
signifiesigned int
toujours, non? À partchar
, dans quels autres types de données ont la même confusionC
?char
c'est le seul type qui peut être signé ou non signé.int
équivaut àsigned int
par exemple.int
est signé ou non signé.Comme le souligne Alok , la norme laisse cela à la mise en œuvre.
Pour gcc, la valeur par défaut est signée, mais vous pouvez la modifier avec
-funsigned-char
. remarque: pour gcc dans Android NDK, la valeur par défaut est non signée . Vous pouvez également demander explicitement des caractères signés avec-fsigned-char
.Sur MSVC, la valeur par défaut est signée mais vous pouvez la modifier avec
/J
.la source
C99 N1256 draft 6.2.5 / 15 "Types" a ceci à dire à propos de la signature du type
char
:et dans une note de bas de page:
la source
Selon le livre The C Programming Language de Dennis Ritchie, qui est le livre standard de facto pour ANSI C, les caractères simples signés ou non signés dépendent de la machine, mais les caractères imprimables sont toujours positifs.
la source
Selon la norme C, la signature de plain char est "définie par l'implémentation".
En général, les implémenteurs ont choisi celui qui était le plus efficace à implémenter sur leur architecture. Sur les systèmes x86, le caractère est généralement signé. Sur les systèmes armés, il n'est généralement pas signé (Apple iOS est une exception).
la source
Selon «Le langage de programmation C ++» de Bjarne Stroustrup,
char
«l'implémentation est définie». Cela peut êtresigned char
ouunsigned char
selon la mise en œuvre. Vous pouvez vérifier s'ilchar
est signé ou non en utilisantstd::numeric_limits<char>::is_signed
.la source
Maintenant, nous savons que la norme laisse cela à la mise en œuvre.
Mais comment vérifier un type est
signed
ouunsigned
, commechar
?J'ai écrit une macro pour faire ceci:
#define IS_UNSIGNED(t) ((t)~1 > 0)
et le tester avec
gcc
,clang
etcl
. Mais je ne suis pas sûr que ce soit toujours sans danger pour les autres cas.la source