52 votes

Pourquoi les flux C++ utilisent-ils char au lieu de unsigned char ?

Je me suis toujours demandé pourquoi la bibliothèque standard C++ a instancié basic_[io]stream et toutes ses variantes en utilisant l'attribut char au lieu du type unsigned char type. char Cela signifie (selon qu'il est signé ou non) que vous pouvez avoir un débordement et un sous-débordement pour des opérations comme get(), ce qui conduira à une valeur définie par l'implémentation des variables concernées. Un autre exemple est celui de la sortie d'un octet, non formaté, vers un ostream en utilisant sa fonction put fonction.

Des idées ?


Note : Je ne suis toujours pas vraiment convaincu. Donc si vous connaissez la réponse définitive, vous pouvez toujours la poster en effet.

25voto

Steve Jessop Points 166970

Il est possible que j'aie mal compris la question, mais la conversion de unsigned char en char n'est pas non spécifiée, elle dépend de l'implémentation (4.7-3 dans la norme C++).

Le type d'un caractère d'un octet en C++ est "char", et non "unsigned char". Cela donne aux implémentations un peu plus de liberté pour faire ce qu'il y a de mieux sur la plate-forme (par exemple, l'organisme de normalisation a pu croire qu'il existe des processeurs où l'arithmétique des octets signés est plus rapide que celle des octets non signés, bien que ce soit une spéculation de ma part). Et aussi pour la compatibilité avec le C. Le résultat de la suppression de ce type d'incertitude existentielle du C++ est le C# ;-)

Étant donné que le type "char" existe, je pense qu'il est logique pour les flux habituels de l'utiliser même si sa signature n'est pas définie. Donc peut-être que la réponse à votre question est la réponse à la question "pourquoi le C++ n'a pas simplement défini le type char comme étant non signé ?

15voto

Daniel Trebbien Points 18089

Je l'ai toujours compris de cette manière : le but de la iostream est de lire et/ou d'écrire un flux de caractères, qui, si l'on y réfléchit, sont des entités abstraites qui ne sont représentées par l'ordinateur qu'à l'aide d'un codage de caractères. La norme C++ se donne beaucoup de mal pour éviter de préciser le codage des caractères, indiquant seulement que "les objets déclarés comme des caractères ( char ) doit être suffisamment grand pour stocker n'importe quel membre du jeu de caractères de base de l'implémentation ", car elle n'a pas besoin de forcer le " jeu de caractères de base de l'implémentation " à définir le langage C++ ; la norme peut laisser la décision de dont est utilisé jusqu'à l'implémentation (compilateur avec une implémentation STL), et notez juste que char représentent des caractères uniques dans un certain codage.

Le rédacteur d'une implémentation pourrait choisir un codage à un octet tel que ISO-8859-1 ou même un encodage double-octet tel que UCS-2 . Cela n'a pas d'importance. Tant qu'un char est "suffisamment grand pour stocker n'importe quel membre du jeu de caractères de base de l'implémentation" (notez que cela interdit explicitement l'utilisation de l'objet codages à longueur variable ), alors l'implémentation peut même choisir un encodage qui représente le latin de base d'une manière incompatible avec tout encodage commun !

Il est déroutant que le char , signed char y unsigned char partagent le terme "char" dans leur nom, mais il est important de garder à l'esprit que char n'appartient pas à la même famille de types fondamentaux que signed char y unsigned char . signed char est dans la famille des types d'entiers signés :

Il y a quatre types d'entiers signés : " signed char ", " short int ", " int " et " long int ".

et unsigned char fait partie de la famille des types d'entiers non signés :

Pour chacun des types d'entiers signés, il existe un type d'entier correspondant (mais différent) type d'entier non signé : "unsigned char", "unsigned short int", "unsigned int" et "unsigned long int", ...

La seule similitude entre les char , signed char y unsigned char est qu'"[ils] occupent la même quantité de stockage et ont les mêmes exigences d'alignement". Ainsi, on peut reinterpret_cast de char * à unsigned char * afin de déterminer la valeur numérique d'un caractère dans le jeu de caractères d'exécution.

Pour répondre à votre question, la raison pour laquelle la STL utilise char comme type par défaut est dû au fait que les flux standard sont destinés à lire et/ou écrire des flux de caractères, représentés par char et non des entiers ( signed char y unsigned char ). L'utilisation de char par rapport à la valeur numérique est un moyen de séparer les préoccupations.

4voto

n-alexander Points 2685

Char est pour les caractères, unsigned char pour les octets de données brutes, et signed chars pour, eh bien, les données signées.

La norme ne précise pas si les chars signés ou non signés seront utilisés pour l'implémentation de char - c'est spécifique au compilateur. Elle spécifie seulement que le "char" sera "suffisant" pour contenir les caractères sur votre système - de la manière dont les caractères étaient à l'époque, c'est-à-dire sans UNICODE.

L'utilisation de "char" pour les caractères est la méthode standard. Utiliser unsigned char est un hack, bien que cela corresponde à l'implémentation de char du compilateur sur la plupart des plateformes.

0voto

baruch Points 4375

Je pense este Ce commentaire l'explique bien. Je cite :

signed char et unsigned char sont des types arithmétiques et intégraux, tout comme int et unsigned int. D'autre part, char est expressément destiné à être le type "E/S" qui représente une unité de données fondamentale opaque et spécifique au système sur votre plate-forme. C'est dans cet esprit que je les utiliserais.

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