3字节整数和5字节长整型?

17

C和C++标准是否允许数值类型的sizeof不是二的幂?

已知以下限制:

  • 16 <= CHAR_BIT * sizeof(int) <= CHAR_BIT * sizeof(long)
  • 32 <= CHAR_BIT * sizeof(long) <= CHAR_BIT * sizeof(long long)
  • 还有其他几个,在典型的8位字节架构上意味着 2 <= sizeof(int) && 4 <= sizeof(long)

这是否意味着sizeof(int) == 3 && sizeof(long) == 5是有效的行为?

如果是,是否已知任何采用类似方式的编译器/体系结构?


8
为什么需要检查这些?只需编写不依赖于类型宽度的可移植代码即可。 - Kerrek SB
2
sizeof(int) <= 4 这个限制从哪里来?在一个 CHAR_BIT == 32 的架构中,我无法想象 sizeof(int) == 1 会无效。 - Angew is no longer proud of SO
1
还有,哪里说 CHAR_BIT * sizeof(int) <= 32 - Angew is no longer proud of SO
确实存在一些64位架构,它们没有更小的可寻址类型;因此它们无法遵守您的“<= 32”约束。 - Mike Seymour
3
有24位的DSP架构;然而,我不知道它们中是否有可寻址的8位字节(这将导致 sizeof(int)==3)。我曾经使用过的唯一架构是 CHAR_BIT==24sizeof(int)==1 - Mike Seymour
1
@MikeSeymour,我所知道的所有24位DSP处理器都有CHAR_BIT == 24sizeof(int) == sizeof(char),但最近我发现Motorola DSP5600x/3xx系列具有16位短整型和24位整型。如果以16位模式运行,它还具有32位长整型。 - phuclv
4个回答

14

我认为3.9.1/2(C++98)很好地概括了这个问题(紧随着无符号类型的类似信息):

  

有四种带符号整数类型:“signed char”、“short int”、“int”和“long int”。在此列表中,每种类型提供的存储空间至少与在列表中排在其前面的类型一样多。普通整数具有执行环境建议的自然大小39);提供其他带符号整数类型以满足特殊需要。

基本上我们只知道sizeof(char) == 1并且每个“较大”的类型至少具有相同的大小,其中int是架构的“自然”大小(据我所知,“自然”大小由编译器编写者决定)。我们不知道像CHAR_BIT * sizeof(int) <= 32 之类的东西。还要记住,CHAR_BIT也不一定是8。

看起来可以比较安全地说,在硬件中允许使用原生大小的情况下,三字节的int和五字节的long将被允许。但是,我不知道是否存在此类硬件/架构。

编辑:如@Nigel Harper评论所指出的那样,我们知道int必须至少为16位,long必须至少为32位才能满足范围要求。除此之外,我们没有任何特定的大小限制,如上所述。


5
一些Unisys大型计算机的sizeof(int)为6(其他一些计算机的CHAR_BIT为9)。旧日的CDC大型计算机有60位的字长,如果使用C语言实现,可能会有CHAR_BIT == 10sizeof(int) == 6。但我不认为曾经有C编译器或者C++为它们开发,这种计算机在20世纪70年代就停产了。 - James Kanze
我们知道 16 <= CHAR_BIT * sizeof(int) - 这意味着 int 至少是一个 16 位类型,这是为了满足标准规定的最小范围。同样,32 <= sizeof(long) * CHAR_BIT。 - Nigel Harper
1
@JamesKanze,CDC架构是我见过的唯一一个int大小(60位)大于指针大小(18位)的架构。此外,使用本地字符集,一个字符是6位,但它们不能单独寻址。 - Mark Ransom
这是C++标准的3.9.1/2,对吧?特别是因为问题同时被标记为C和C++,所以明确指定非常重要。 - Keith Thompson
@MarkRansom 是的,但是使用6位字符的C实现将不合法。而且C还要求int中的char数量必须是整数(通常PDP-10解决方案是在36位字中放置5个7位char,这也是不合法的),因此我们被迫使用10位。指令集显然假定字节为12位,因此可能更适合使用12位charsizeof(int) == 5。(但我只是猜测。我从未在该机器上实际编写过汇编程序。) - James Kanze

11

简短总结

这种行为是有效的,而且确实有这样的编译器/架构存在。

  • TI C5500/C6000 采用4字节的 int 和 5字节的 long
  • Motorola DSP5600x/3xx 系列采用2字节的 short、3字节的 int 和6字节的 long
  • x86 采用8字节的 double 和 10字节的 long double

用来表示类型 long 的位数并不总是和类型 int 相同或者是前者的整数倍。需要表示更大范围内的值(比 int 类型支持的要大)可能是必须的,但处理器成本也可能是一个考虑因素...

Derek M. Jones 的 The New C Standard (摘录) - 经济与文化评论


其他答案已经概括了 C++ 标准的要求。同样地,C 标准也没有限制字节数为 2 的幂次方的整数或浮点数类型大小。最常见的例子是 long double,在 x86 上通常为 10 字节(在许多现代编译器中填充为 12 或 16 字节)。

ISO/IEC 9899:1999 (E)

5.2.4.2.1 整数类型的大小 <limits.h>

  1. 下面给出的值应替换为适用于 #if 预处理指令的常量表达式。此外,除了CHAR_BITMB_LEN_MAX 之外,以下应替换为表达式,其类型与将按整数提升转换后成为相应类型的对象的表达式相同。它们的实现定义值的绝对值(大小)应等于或大于所示值,并具有相同的符号。 [...]

6.2.5 类型

  1. 有五种标准带符号整数类型,分别称为 signed charshort intintlong intlong long int。(这些及其他类型可以用几种额外方式进行指定,如 6.7.2 中所述。)还可能有实现定义的扩展带符号整数类型。28)

    标准和扩展的带符号整数类型统称为带符号整数类型。29)

  2. 对于任何两个具有相同符号并且不同整数转换级别(见 6.3.1.1)的整数类型,较小整数转换级别类型的值范围是另一类型的值范围的子集


奇数大小的整数类型非常罕见,但仍然存在。许多 DSP 具有符合标准的编译器,具有 非2的幂类型,其中 int 有 32 位,long40位

long 的大小为

  • 对于 C6000 COFF,为 40 位或 5 个字节。这完全符合主要 C/C++ 标准的任何最低需求,因为这些标准都定义了 long(即 long int)的最小要求为 4 字节。程序员经常错误地假设此类型的大小恰好为 4 个字节。

强调是我的Emphasis mine
TICI编译器对C89支持的误解#关于TI C的误解

旁注:在某些TI目标平台上,即使long long也是32位或40位类型,这在C89中作为扩展是有效的,但违反了C99

一些目标平台有long long(来自C99的扩展),但不符合规范。C99要求至少64位,但C2700有32位的long long,C5500有40位的long long。C2800、C6000和ARM有64位的long long,而C5400和MSP430则不支持long long。这在技术上不是违反C89,因为这实际上是一种扩展,但如果我们开始支持C99,这将违反C99(C99 5.2.4.2.1“整数类型的大小<limits.h>”第1段)。

更宽的类型的大小甚至不需要是其前一个类型大小的倍数。继续引用Derek M. Jones在“新C标准(摘录材料):经济和文化评论”中所说的话

例如,德州仪器公司的TMS320C6000 DSP处理器使用32位来表示类型int,并使用40位来表示类型long(这种选择并不罕见)。那些用24位来表示类型int的处理器(通常是DSP),通常会用48位来表示类型long。使用24/48位整数类型表示可以受到应用要求的驱动,在这些要求中,32/64位整数类型表示不具备成本效益。
在我之前所知道的所有24位DSP中,CHAR_BIT == 24,并且所有类型的大小都是24位的倍数,但我刚刚发现摩托罗拉DSP5600x / 3xx系列有一个非常“奇怪”的类型系统。
因此,在这种情况下,sizeof(char) == 1sizeof(short) == 2,但sizeof(int) == 3,而sizeof(long) == 6

不幸的是,GCC将它们(longlong long)称为双字整数,并且大多数人也这样称呼,造成了很大的误解,尽管它的大小不一定是两倍。


1
C++标准(几乎可以确定的是C标准,但我很久没有看过它了)没有规定类型应该有多少位。我知道9位char是被允许的,并且有一些机器有36位整数。上次我检查时,9和36都不是2的幂次方。

3
但是在该平台上,sizeof(int)将为4,这是2的幂。我不确定原帖作者是否意味着sizeof(x)必须是2的幂,还是sizeof(x) * CHAR_BIT - Sebastian Redl
1
@SebastianRedl,我的意思是 sizeof(type),而不是 sizeof(type) * CHAR_BIT - sasha.sochka
2
然而,在标准中并没有禁止这两种情况。在构建硬件时使用2的幂可能是实用的,但那是另一回事。 - Mats Petersson
1
无论如何,如果您将浮点类型包含在数字类型中,即使在x86上也有一个简单的反例:我认为在MSVC中sizeof(long double)== 10。除非它超对齐了,但我不认为会这样。 - Sebastian Redl
@SebastianRedl在MSVC中提到sizeof(long double)==8,可以在这里看到。他们根本不支持80位长双精度浮点数。不过对于GCC来说,你的例子是正确的,在32位x86中sizeof(long double)==10 - Ruslan

1

24位整数并不意味着sizeof(int)为3。OP询问的是奇怪的sizeof,而不是位数大小奇怪。 - phuclv
我认为在当前情况下可以假定一个字节由8位组成,除非另有说明。 - Johan Kotlinski
1
不行。有很多DSP架构都有16、24或32位字符。假设任何事情都是不安全的。在stackoverflow上有数百个关于这个问题的问题,你应该在做出假设之前先阅读一些。 - phuclv
谢谢您的智慧,但这与原问题有什么关系呢? - Johan Kotlinski
2
好的,在那些24位架构中,CHAR_BIT == 24,因此 sizeof(char) == sizeof(short) == sizeof(int) == 1,而且 int 是1字节,因此所有大小仍然是2的幂。 OP感兴趣的是大小不是2的幂的情况。 - phuclv
显示剩余4条评论

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