Y a-t-il des machines, où sizeof (char)! = 1, ou au moins CHAR_BIT> 8?

93

Y a-t-il des machines (ou des compilateurs), où sizeof(char) != 1?

La norme C99 indique- t-elle que la sizeof(char)mise en œuvre de la conformité standard DOIT être exactement 1? Si c'est le cas, veuillez me donner le numéro de section et la citation.

Mise à jour: Si j'ai une machine (CPU), qui ne peut pas adresser les octets (la lecture minimale est de 4 octets, alignés), mais seulement 4-s d'octets ( uint32_t), le compilateur pour cette machine peut-il définir sizeof(char)à 4? sizeof(char)sera 1, mais char aura 32 bits ( CHAR_BITmacros)

Update2: Mais la taille du résultat n'est PAS un BYTES! c'est la taille de CHAR. Et char peut être 2 octets, ou (peut-être) 7 bits?

Update3: Ok. Toutes les machines ont sizeof(char) == 1. Mais quelles machines ont CHAR_BIT > 8?

osgx
la source
4
Je suis préoccupé par la conformité à la norme C99. Je travaille en étroite collaboration avec des compilateurs C99
osgx
2
Comme Unicode devient encore plus important, il peut arriver des compilateurs non standard qui utilisent des caractères Unicode comme char(au lieu de wchar). Même si la norme dit que cela sizeof(char)doit être 1, je ne me fierais pas à cette hypothèse.
Chip Uni
14
il n'y a pas de compilateurs C où sizeof (char) n'est pas 1, unicode ou non.
nos
6
@Chip: sizeof(char)vaut toujours 1, même si char est de 32 bits (comme cela se produit sur certains systèmes). C a beaucoup de verrues amusantes.
Nick Bastin
2
Toutes les versions de la norme C exigent que CHAR_BIT soit au moins égal à 8; vous ne pouvez pas avoir CHAR_BIT == 7 et être conforme à la norme. Cependant, il est parfaitement possible pour les machines d'avoir CHAR_BIT> 8. Les anciennes machines Cray en avaient, je crois ( sizeof(char) == sizeof(short) && sizeof(char) == sizeof(int)sur celles-ci; je ne me souviens pas sizeof(int) == sizeof(long)si CHAR_BIT avait 32 ou 64; je suppose que c'était 32, et je pense sizeof(long) == 1aussi. (Vous pouvez trouver une référence, mais pas un accès en ligne, à un manuel Cray C ).
Jonathan Leffler

Réponses:

91

Il en est toujours un dans C99, section 6.5.3.4:

Lorsqu'il est appliqué à un opérande de type char, unsigned char ou signé char, (ou une version qualifiée de celui-ci), le résultat est 1.

Edit: ne fait pas partie de votre question, mais pour l'intérêt de Harbison et Steele, 3e éd. (avant c99) p. 148:

Une unité de stockage est considérée comme la quantité de stockage occupée par un caractère; la taille d'un objet de type charest donc 1.

Edit: En réponse à votre question mise à jour, la question et la réponse suivantes de Harbison et Steele sont pertinentes (ibid, Ex.4 du Ch.6):

Est-il permis d'avoir une implémentation C dans laquelle le type charpeut représenter des valeurs allant de -2 147 483 648 à 2 147 483 647? Dans l'affirmative, que serait sizeof(char) cette mise en œuvre? Quelles seraient les gammes les plus petites et les plus grandes de type int?

Réponse (ibid, p. 382):

Il est permis (en cas de gaspillage) pour une implémentation d'utiliser 32 bits pour représenter le type char . Quelle que soit l'implémentation, la valeur de sizeof(char)est toujours 1.

Bien que cela ne traite pas spécifiquement d'un cas où, disons que les octets sont 8 bits et char sont 4 de ces octets (en fait impossible avec la définition c99, voir ci-dessous), le fait que cela sizeof(char) = 1ressort toujours clairement de la norme c99 et de Harbison et Steele.

Edit: En fait (c'est en réponse à votre question upd 2), en ce qui concerne c99 sizeof(char) est en octets, à partir de la section 6.5.3.4 encore:

L'opérateur sizeof donne la taille (en octets) de son opérande

ainsi combiné avec la citation ci-dessus, des octets de 8 bits et char4 de ces octets est impossible: pour c99, un octet équivaut à a char.

En réponse à votre évocation de la possibilité d'un 7 bits char : ce n'est pas possible en c99. Selon la section 5.2.4.2.1 de la norme, le minimum est de 8:

Leurs valeurs définies par l'implémentation doivent être égales ou supérieures [je souligne] en grandeur à celles indiquées, avec le même signe.

- nombre de bits pour le plus petit objet qui n'est pas un champ de bits (octet)

 **CHAR_BIT 8**

- valeur minimale pour un objet de type char signé

**SCHAR_MIN -127//−(27−1)** 

- valeur maximale pour un objet de type char signé

**SCHAR_MAX +127//27−1** 

- valeur maximale pour un objet de type char non signé

**UCHAR_MAX 255//28−1** 

- valeur minimale pour un objet de type char

**CHAR_MIN**    see below 

- valeur maximale pour un objet de type char

**CHAR_MAX**    see below

[...]

Si la valeur d'un objet de type char est traitée comme un entier signé lorsqu'il est utilisé dans une expression, la valeur de CHAR_MIN doit être la même que celle de SCHAR_MIN et la valeur de CHAR_MAX doit être la même que celle de SCHAR_MAX. Sinon, la valeur de CHAR_MIN doit être 0 et la valeur de CHAR_MAX doit être la même que celle de UCHAR_MAX. La valeur UCHAR_MAX sera égale à 2 ^ CHAR_BIT - 1.

Ramashalanka
la source
9
Remarque additionnelle. il y a une macro CHAR_BITS qui vous dira combien de bits sont vos caractères.
nos
1
Les données complètes de ce grand livre sont celles de Harbison et Steele. C: A Reference Manual, Third Edition, Prentice Hall, 1991
osgx
2
Si vous savez que vous travaillez avec des types char et que vous savez que le langage les oblige à avoir une taille de 1, pourquoi est-ce une bonne idée de toujours mettre la taille redondante de (char)?
1
(a) et (c) ont des ramifications beaucoup plus sérieuses que cela ne peut pas espérer résoudre, ni même se rapprocher de résoudre; aussi YAGNI. Quelqu'un comme dans (b) a juste besoin d'être dit une fois - je n'ai pas besoin de leur apprendre dans chaque ligne de mon code. Cependant, il y a des inconvénients à utiliser sizeof(char): c'est un autre élément à débattre / vérifier / etc. dans vos conventions de codage / normes / directives, me fait perdre mon temps à me demander si vous connaissez vraiment C et quoi d'autre peut être incorrect, prend de la «bande passante» visuelle / mentale / text-line.
1
@Ramashalanka: Oui, le code compilé est équivalent. Ce sont tous les problèmes de lisibilité et de la manière dont les gens utilisent le code source dont je parle. (Et FWIW, je pense que vous avez une réponse +1 décente ici, je trouve juste que "toujours utiliser sizeof (char)" est erroné et un problème de hotbutton pour moi, même s'il s'agit d'un petit problème.)
21

Il n'y a pas de machines avec sizeof(char)4. C'est toujours 1 octet. Cet octet peut contenir 32 bits, mais en ce qui concerne le compilateur C, c'est un octet. Pour plus de détails, je vais vous diriger vers la FAQ C ++ 26.6 . Ce lien le couvre assez bien et je suis assez certain que C ++ a obtenu toutes ces règles de C. Vous pouvez également consulter la FAQ 8.10 de comp.lang.c pour les caractères de plus de 8 bits.

Upd2: Mais la taille du résultat n'est PAS un BYTES! c'est la taille de CHAR. Et char peut être 2 octets, ou (peut-être) 7 bits?

Oui, ce sont des octets. Permettez-moi de le dire encore. sizeof(char)est de 1 octet selon le compilateur C. Ce que les gens appellent familièrement un octet (8 bits) n'est pas nécessairement le même que ce que le compilateur C appelle un octet. Le nombre de bits dans un octet C varie en fonction de l'architecture de votre machine. Il est également garanti être d'au moins 8.

Michael Kristofik
la source
3
S'il vous plaît!!! C ++ est le langage vraiment DIFFÉRENT de C (C99). Cette question concerne uniquement le C pur.
osgx
<strike> Que puis-je faire lorsque la machine / CPU ne peut pas accéder aux octets 8 bits? L'accès non aligné est interdit. </strike> (Même sur x86, malloc retourne des données alignées et alloue de la mémoire par multiplication de 4 octets.) <strike> Alors CHAT_BIT sera supérieur à 8. Oui, une telle plate-forme peut être assez spéciale. </ Strike >
osgx
10
@osgx, j'ai tendance à crier autant que vous venez de le faire quand les gens essaient de mélanger C et C ++. Mais je pense que dans ce cas , une entrée de FAQ C ++ s'applique également bien à C.
Michael Kristofik
3
Le nom correct pour "8 bits" est octet. La norme C utilise le mot «octet» pour un objet de la taille d'un caractère. D'autres peuvent utiliser le mot «octet» de différentes manières, souvent quand ils signifient «octet», mais en C (et C ++, ou Objective-C) cela signifie «objet de la taille d'un caractère». Un caractère peut avoir plus de 8 bits ou plus d'un octet, mais il s'agit toujours d'un octet.
gnasher729
9

PDP-10 et PDP-11 l' étaient.

Mise à jour: il n'y a pas de compilateurs C99 pour PDP-10.

Certains modèles de DSP SHARC 32 bits d'Analog Devices ont CHAR_BIT = 32 et le DSP Texas Instruments de TMS32F28xx a CHAR_BIT = 16, apparemment .

Mise à jour: Il existe GCC 3.2 pour PDP-10 avec CHAR_BIT = 9 (vérifiez include / limits.h dans cette archive).

osgx
la source
1
Ne confondez pas les implémentations de langages similaires mais pas C avec C. Vous avez même dit "Je suis inquiet de la conformité à la norme C99. Je travaille en étroite collaboration avec les compilateurs C99."
2
@Roger: Il n'est pas juste d'appeler GCC3 non conforme à C99, sauf si vous avez affaire à des cas extrêmes qui sont considérés comme des bogues dans GCC.
Joshua
1
@Joshua, je pense que Roger parle des compilateurs historiques de K&R et de pcc. Il n'est pas non plus juste de prétendre qu'il est conforme à C99 avant que la suite de tests de conformité C99 ne soit exécutée sur PDP-10, lorsqu'elle est compilée avec ce port (il peut y avoir des bogues dus au portage et à la machine elle-même). Mais on peut s'attendre à ce qu'il soit proche de la norme C99, tout comme GCC3.2 sur x86.
osgx
1
@Joshua: CHAR_BIT est autorisé, en C99, à être supérieur à 8, mais sizeof (char) doit toujours être 1 (et cette réponse était très différente lorsque j'ai laissé ce commentaire). Je n'appelle pas GCC3 non conforme, et C89 fait la même exigence ici, BTW. J'ai cité ce texte pour dire que osgx est celui qui s'inquiète de la conformité C99 et utilise des compilateurs C99, alors pourquoi s'inquiète-t-il des compilateurs non-C99?
2
Auteur du PDP-10 GCC ici. CHAR_BIT est 9, mais sizeof (char) est toujours 1.
Lars Brinkhoff