是否存在sizeof(char) != 1,或者至少CHAR_BIT > 8的机器?

113

有没有机器(或编译器)的sizeof(char) != 1

C99标准是否规定,在符合标准的实现中,sizeof(char)必须恰好为1?如果是,请给出节号和引用。

更新: 如果我有一台不能寻址字节(最小读取量是4字节,对齐的)但只能寻址4字节(uint32_t)的机器(CPU),这种机器上的编译器能否将sizeof(char)定义为4? sizeof(char)将为1,但char将具有32位CHAR_BIT宏)

更新2:sizeof的结果不是字节!它是CHAR的大小。Char可能是2个字节,或者(可能)是7位?

更新3: 好吧,所有机器都有sizeof(char)==1。但是哪些机器有CHAR_BIT >8


4
我担心是否符合C99标准。我与C99编译器密切合作。 - osgx
2
随着Unicode的重要性日益增强,可能会出现使用Unicode字符作为 char(而不是wchar)的非标准编译器。即使标准规定 sizeof(char) 必须为1,我也不会依赖这个假设。 - Chip Uni
16
无论是否使用Unicode,只要char的大小不为1,就不存在C编译器。 - nos
7
@Chip: sizeof(char) 的值始终为1,即使char在某些系统上是32位的(这种情况确实存在)。C语言有很多有趣的缺陷。 - Nick Bastin
2
所有版本的C标准都要求CHAR_BIT至少为8;你不能有CHAR_BIT == 7并符合标准。然而,机器具有CHAR_BIT > 8是完全可行的。我相信旧的Cray机器就是这样(在这些机器上sizeof(char) == sizeof(short) && sizeof(char) == sizeof(int); 我不记得sizeof(int) == sizeof(long)或者CHAR_BIT是32还是64; 我预计它是32,我认为sizeof(long) == 1也是如此。(你可以找到一个关于Cray C手册的参考,但无法在线访问)。 - Jonathan Leffler
显示剩余5条评论
3个回答

103

在C99中,第6.5.3.4节中始终为1:

当应用于具有类型charunsigned charsigned char(或其限定版本)的操作数时,结果为1

编辑:不是你的问题的一部分,但来自Harbison和Steele的C:参考手册,第三版,Prentice Hall,1991(c99之前)p.148的趣味内容:

存储单元被认为是 一个字符占用的存储量;因此,类型为char的对象的大小为1

编辑:回答您更新后的问题,来自Harbison和Steele的以下问题和答案相关(ibid,第6章的Ex. 4):

是否允许在C实现中,类型char可以表示从-2,147,483,648到2,147,483,647的值?如果是这样,那么在该实现下sizeof(char)将是多少?int类型的最小和最大范围是什么?

答案(ibid,第382页):

允许(虽然浪费)使用32位来表示类型char。无论实现方式如何,sizeof(char)的值始终为1。

虽然这并没有明确回答当字节为8位且char为其中的4个字节的情况(实际上在c99定义中不可能,见下文),但是sizeof(char) = 1这一事实在c99标准和Harbison和Steele中都非常清楚。

编辑:实际上(这是针对您的第二个问题的回答),就c99而言,sizeof(char) 以字节为单位,同样来自于6.5.3.4节:

sizeof运算符返回其操作数的大小(以字节为单位)

所以结合以上引用,8位字节和char作为其中的4个字节是不可能的:对于c99,一个字节与一个char相同。

针对您提到的7位char的可能性:在c99中不可能。根据标准的5.2.4.2.1节,最小值为8:

他们的实现定义值应该等于或大于这些值的大小,符号相同。
- 不是位域的最小对象(字节)的位数 CHAR_BIT 8
- 类型为signed char的对象的最小值 SCHAR_MIN -127
- 类型为signed char的对象的最大值 SCHAR_MAX +127
- 类型为unsigned char的对象的最大值 UCHAR_MAX 255
- 类型为char的对象的最小值 CHAR_MIN 参见下文
- 类型为char的对象的最大值 CHAR_MAX 参见下文
如果将char类型的对象的值在表达式中作为有符号整数处理,则CHAR_MIN的值应与SCHAR_MIN的值相同,CHAR_MAX的值应与SCHAR_MAX的值相同。否则,CHAR_MIN的值应为0,CHAR_MAX的值应与UCHAR_MAX的值相同。值UCHAR_MAX应等于2^CHAR_BIT-1。

4
如果您知道正在使用char类型,并且了解语言要求它们的大小为1,那么为什么总是在其后加上冗余的sizeof(char)会是一个好主意呢? - Roger Pate
2
@Roger。一般来说,使用sizeof以实现独立性非常重要。是的,在上述所有情况下,char是一个例外,可以安全地假设sizeof(char)=1。我之所以说“好主意”,是因为:(a) 如果有人后来改用了,比如,long,它降低了出错的机会,因为sizeof(char)作为一个提醒,(b) 一个代码阅读者,比如OP,对于sizeof(char)不确定的情况下,不会浪费时间担心代码是否正确,(c) 当前非标准或未来的实现(不太可能)。这就是我的习惯的原因。 - Ramashalanka
2
(a)和(c)有更严重的后果,这是无法解决甚至接近解决的;还有YAGNI。像(b)这样的人只需要被告知一次——我不需要在我的每一行代码中教他们。然而,使用sizeof(char)也有缺点:它是另一个要在您的编码约定/标准/指南中进行辩论/检查等的项目,浪费了我的时间,让我想知道您是否真正了解C以及可能存在什么其他错误,占用了视觉/心理/文本行“带宽”。 - Roger Pate
2
@Ramashalanka:是的,编译后的代码是等效的。我说的是与可读性有关的所有问题,以及人们如何使用源代码。(顺便说一句,我认为你在这里给出了一个不错的+1答案,只是我认为“始终使用sizeof(char)”是误导性的,并且对我来说是一个敏感的问题,即使它只是一个小问题。) - Roger Pate
1
@Ramashalanka:虽然我认为这是一个主观的事情。如果一些人真的想使用它,并始终如一地使用它,那也没问题。但在我看来,没有必要这样做,因为如果你不能相信sizeof(char) == 1将保持不变,那么你实际上什么都不能信任。 - mk12
显示剩余3条评论

23

没有机器的 sizeof(char) 是4。它总是1个字节。这个字节可能包含32位,但就C编译器而言,它只是一个字节。有关更多细节,我会指向 C++ FAQ 26.6。该链接覆盖得非常好,我相当确定C++从C那里得到了所有这些规则。您还可以查看comp.lang.c FAQ 8.10以了解大于8位的字符。

更新2:但 sizeof 结果不是 BYTES!它是 CHAR 的大小。 Char 可以是2字节,或者(可能)是7位?

是的,它是字节。让我再说一遍。按照C编译器的说法,sizeof(char)是1个字节。人们口头上所说的一个字节(8位)不一定与C编译器所说的一个字节相同。C字节中的位数取决于您的机器体系结构。它也保证至少为8个位。


6
请注意!C++是与C(C99)截然不同的语言。这个问题仅涉及纯C语言。 - osgx
当机器/CPU无法访问8位字节时,我该怎么办?不允许非对齐访问。(即使在x86上,malloc也返回对齐的数据,并分配以4个字节为倍数的内存。)那么CHAT_BIT将大于8。是的,这样的平台可能非常特殊。 - osgx
12
@osgx,当人们尝试混用C和C ++时,我往往会像你刚才那样尖叫。但我认为在这种情况下,一个C ++ FAQ条目同样适用于C。 - Michael Kristofik
7
“8 bits”的正确名称是“八位组”。C标准中使用“字节”表示与char大小相同的对象。其他人可能会以不同的方式使用“字节”,通常指的是“八位组”,但在C(和C ++或Objective-C)中,“字节”表示“char大小的对象”。char可能超过8位,或超过一个八位组,但它始终是一个字节。 - gnasher729
德州仪器有带有16位字符的微控制器。 - Prof. Falken

16

PDP-10曾经存在。

更新: PDP-10上似乎没有C99编译器。

一些模型的Analog Devices 32位SHARC DSP具有CHAR_BIT=32,而TMS32F28xx的Texas Instruments DSP具有CHAR_BIT=16,据报道

更新: PDP-10有GCC 3.2,CHAR_BIT=9(在该存档中检查include/limits.h)。


1
不要把类似但不同于C语言的实现与C语言混淆。你甚至说过:“我担心C99标准的兼容性。我密切与C99编译器合作。” - Roger Pate
2
@Roger:除非你处理GCC中被认为是错误的极端边缘情况,否则称GCC3不符合C99标准是不公平的。 - Joshua
2
@Joshua,我认为Roger是在谈论K&R和pcc历史编译器。在运行此端口编译时(可能存在来自移植和机器本身的错误),在对PDP-10运行C99合规性测试套件之前,声称它符合C99不公平。但可以期望它接近于C99标准,就像GCC3.2在x86上一样。 - osgx
1
@Joshua:在C99中,CHAR_BIT允许大于8,但sizeof(char)仍必须为1(当我留下该评论时,此答案差异很大)。我并不是在说GCC3不符合标准,顺便说一句,C89在这里也有同样的要求。我引用了那段文字来表明osgxis担心C99的兼容性,并使用C99编译器,那么他为什么还担心非C99编译器呢? - Roger Pate
我对“C99标准合规性”很感兴趣。为此,我想找出C99和非C99编译器在某些问题边缘的差异,并找出它们所允许和不允许的内容。(例如,请参见我的有关消除无限循环的问题) - osgx
7
PDP-10 GCC 的作者在这里。CHAR_BIT 是 9,但 sizeof(char) 仍然是 1。 (注:CHAR_BIT 指每个 char 类型的位数,通常为 8,但在某些系统中可以不同,例如这里的 PDP-10 系统) - Lars Brinkhoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接