16

C 和 C++ 标准是否都允许sizeof数字类型不是2 的幂?

以下约束是已知的:

  • 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是一种有效的行为?

如果是 - 是否有任何已知的编译器/架构以类似的方式表现?

4

4 回答 4

13

我认为 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。

可以肯定地说,对于本机使用这些大小的硬件,允许使用3 字节int和 5 字节。long但是,我不知道有任何此类硬件/架构。

编辑:正如@Nigel Harper 评论中所指出的,我们确实知道int必须至少有 16 位和long至少 32 位才能满足范围要求。否则,我们没有任何特定的尺寸限制,除了上面看到的。

于 2013-07-24T13:13:20.250 回答
11

TL;博士

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

  • TI C5500/C6000 带 4 字节int、5 字节long
  • 摩托罗拉 DSP5600x/3xx 系列带 2 字节short、3 字节int、6 字节long
  • x86 8-byte double, 10-bytelong double

用于表示类型的位数long并不总是与类型中的位数相同或整数倍int。可能需要能够表示更大范围的值(比 int 类型可能),但处理器成本也可能是一个考虑因素......

Derek M. Jones 的新 C 标准(节选材料)——经济和文化评论


另一个答案已经概括了 C++ 标准要求。同样,C 标准也没有将类型(浮点或整数)大小(以字节为单位)限制为 2 的幂。最常见的示例是long double,在 x86 中通常为 10 字节(在许多现代版本中填充为 12 或 16 字节)编译器)。

ISO/IEC 9899:1999 (E)

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

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

6.2.5 类型

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

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

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


奇数大小的整数类型要少得多,但仍然存在。许多 DSP 具有符合标准的编译器,具有32 位和40 位的非幂或 2 类型intlong

long

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

强调我
在 TI 编译器中对 C89 的支持#对 TI C 的误解

越位说明:在某些 TI 目标上,甚至long long也是 32 位或 40 位类型,这在 C89 中作为扩展有效,但违反 C99

一些目标有long long(C99 的扩展),但不是符合标准的。C99 至少需要 64 位,但 C2700 有 32-bit long long,而 C5500 有 40-bit 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 位来表示类型的处理器(通常是 DSP)int,往往使用 48 位来表示类型long。24/48 位整数类型表示的使用可以由 32/64 位整数类型表示不具成本效益的应用需求驱动。

在我之前知道的所有 24 位 DSP 中,CHAR_BIT == 24所有类型的大小都是 24 位的倍数,但我刚刚发现摩托罗拉 DSP5600x/3xx 系列有一个非常“奇怪”的类型系统

数据类型 位大小
(无符号的字符 8
(un)signed short 16
(un)signed int 24
(un)signed long 48
(长)_fract 24 (48)
指针 16/24
浮动/双 24+8
枚举 24

所以在这种情况下sizeof(char) == 1and sizeof(short) == 2but sizeof(int) == 3andsizeof(long) == 6

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

于 2015-02-05T19:23:13.613 回答
1

肯定有 24 位整数的平台。这在今天仍然用于某些嵌入式应用程序。您可以查看维基百科以获取更多信息:http ://en.wikipedia.org/wiki/24-bit

于 2013-07-24T16:26:17.273 回答
1

C++ 标准(几乎可以肯定是 C 标准,但我已经很长时间没有看过它了)没有一条规则来说明类型应该是多少位。我知道允许使用 9 位char,并且有些机器具有 36 位整数。上次我检查时,9 或 36 都不是 2 的幂。

于 2013-07-24T13:14:21.747 回答