47 votes

Pourquoi les normes C ou C ++ ne définissent-elles pas explicitement char comme signée ou non signée?

 int main()
{
    char c = 0xff;
    bool b = 0xff == c;
    // Under most C/C++ compilers' default options, b is FALSE!!!
}
 

Ni la norme C, ni la norme C ++ ne spécifient char car signé ou non signé, il est défini par l'implémentation.

Pourquoi la norme C / C ++ ne définit-elle pas explicitement le caractère signé ou non signé pour éviter des utilisations dangereuses comme le code ci-dessus?

53voto

Keith Thompson Points 85120

Des raisons historiques, la plupart du temps.

Les Expressions de type char sont promues int dans la plupart des contextes (parce que beaucoup de Processeurs n'ont pas de 8-bits des opérations arithmétiques). Sur certains systèmes, l'extension du signe est le moyen le plus efficace pour ce faire, ce qui plaide pour la fabrication de plain char signé.

D'autre part, le jeu de caractères EBCDIC a des caractères de base avec l'ensemble de bits (c'est à dire, les personnages avec des valeurs de 128 ou plus); sur CES plateformes, char assez bien pour ne pas être signé.

L' ANSI C Justification (pour l'1989 standard) qui n'a pas beaucoup à dire sur le sujet; la section 3.1.2.5 dit:

Trois types de char sont spécifiés: signed, en plaine, et unsigned. Un plaine char peut être représenté que soit signé ou non signé, selon lors de la mise en œuvre, comme dans la pratique antérieure. Le type signed char a été introduit pour rendre disponible un octet signé de type entier sur ces systèmes qui mettent en œuvre la plaine de char non signés. Pour des raisons de la symétrie, le mot-clé signed est admise comme partie du nom de type de d'autres types intégraux.

En remontant plus loin, une première version de la C Manuel de Référence à partir de 1975 dit:

Un char objet peut être utilisé partout où un int peut-être. Dans tous les cas, l' char est converti en int par la multiplication de sa signature par le haut 8 bits de la résultante entier. Ceci est cohérent avec les deux en complément de la représentation utilisée pour les deux personnages et les nombres entiers. (Cependant, le signe-propagation caractéristique disparaît dans d'autres les implémentations.)

Cette description est plus spécifique à l'implémentation de ce que nous voyons dans les documents ultérieures, mais il ne reconnaissez char peut être soit signé ou non signé. Sur les "autres applications" sur lequel "le signe de propagation disparaît", la promotion de l' char objet d' int aurait zéro-extension de la 8-bits de la représentation, essentiellement de la traiter comme une 8-bits non signé de la quantité. (La langue n'a pas encore l' signed ou unsigned mot-clé.)

C prédécesseur immédiat a été une langue appelée B. B est un sans type de langue, de sorte que la question de l' char signé ou non signé ne s'applique pas. Pour plus d'informations sur les débuts de l'histoire de C, voir la fin de Dennis Ritchie, page d'accueil.

Comme pour ce qui se passe dans votre code (application moderne C règles):

char c = 0xff;
bool b = 0xff == c;

Si plain char est non signé, puis l'initialisation de c il met à la (char)0xff, qui se compare égal à 0xff dans la deuxième ligne. Mais si plain char est signé, alors 0xff (une expression de type int) est converti en char -- mais depuis 0xff dépasse CHAR_MAX (en supposant CHAR_BIT==8), le résultat est la mise en œuvre définies. Dans la plupart des implémentations, le résultat est -1. Dans la comparaison, 0xff == c, les deux opérandes sont convertis en int, ce qui équivaut à 0xff == -1ou 255 == -1, ce qui est évidemment faux.

Une autre chose importante à noter est que l' unsigned char, signed char, et (brut) char sont de trois types distincts. char a la même représentation que soit unsigned char ou signed char; il est de la mise en œuvre définies par lequel il est. (D'un autre côté, signed int et int sont deux noms pour le même type; unsigned int est un type distinct. (Sauf que, juste pour ajouter à la frivolité, c'est la mise en œuvre-définir si un champ de bits déclaré brut int est signé ou non signé.))

Oui, c'est un peu le bazar, et je suis sûr qu'il aurait pu être définies différemment si C ont été conçus à partir de zéro aujourd'hui. Mais chaque révision du langage C a eu pour éviter de casser (un peu trop) du code existant, et dans une moindre mesure implémentations existantes.

0voto

Lưu Vĩnh Phúc Points 3183

le caractère à la première est destinée à stocker des caractères, donc, signés ou non n'est pas important. Ce qui importe vraiment est de savoir comment effectuer des mathématiques sur le char de manière efficace. Donc, dépendent du système, le compilateur va choisir ce qui est le plus approprié

Avant ARMv4, BRAS avait pas de support natif pour le chargement halfwords et signé octets. Pour charger un octet signé vous avez eu à LDRB puis connectez-vous étendre la valeur (LSL jusqu'alors ASR vers le bas). C'est douloureux si char est signé par défaut.

http://stackoverflow.com/a/6532932/995714

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X