c - 是否保证每个 C 数据类型的大小都是字节的整数倍?

标签 c c11 c89

我知道 sizeof(char) 永远是 1,而且它是以字节为单位的,一个字节可以是任意位数(我相信大于或等于 8 的任意位数,但不是对此持肯定态度)。

我也经常看到提到如何根据大小之间的关系来指定 C 数据类型大小的引用资料,例如“sizeof(int) <= sizeof(long)”。

我的问题基本上是:在字节为 8 位而 int 为 39 位(或不能被 CHAR_BIT 整除的其他值)的系统上,“sizeof(int)”的计算结果是什么。

我的猜测是 sizeof() 返回存储类型所需的最小字节数,因此它会四舍五入到下一个字节。因此,在我使用 39 位 int 的示例中,sizeof(int) 的结果将为 5。

这是正确的吗?

此外,是否有一种简单的方法可以确定特定类型可以容纳的位数,即 100% 可移植且不需要包含任何 header ?这更像是一种学习体验,而不是实际应用。我只会在实践中使用 stdint 类型。我当时在想,也许是声明变量并将其初始化为 ~0,然后循环并左移它直到它为零。

谢谢!

最佳答案

人们常常无法理解的是,在 C 语言中,sizeof 和“width”之间有着明显的区别。

“宽度”更多是关于二进制表示、范围、溢出/环绕行为。你说一个无符号整数类型是 16 位宽那么你的意思是它在 65535 处回绕。

然而 sizeof 只关心存储。因此,sizeof(T[n])==sizeof(T)*n 是通过允许 sizeof 包含填充来维护的。

因此,试图在 sizeof 类型和类型的算术行为之间寻找联系毫无意义:类型可以有一定的范围,但可以占用它想要的任何存储空间。

为了回答您的问题(“如果在 8 位字符机器上使用 39 位整数会怎么样?”)我想以 TI C6400+ 为例,因为它有一个 40 位的 long 和 8 位字符,非常接近。

TI C6400+ 是字节寻址机器,所以它必须将 8 位字节定义为 char

它还有一个 40 位整数类型,因为 ALU 可以对 40 位整数进行运算,他们将其定义为 long

你会认为 sizeof(long) 应该是 5,对吧?

嗯,它可以,但是这个 CPU 也不能很好地支持未对齐加载,所以出于性能原因,这个 long 类型默认对齐到 8 字节边界而不是 5 字节,然后每个 long 都有 3 个字节的填充(在内存和寄存器级别,因为它在 CPU 中也需要一对 GPR),然后 sizeof(long) 自然变成8.

有趣的是,C6400+ C 实现还提供了 long long 并且 sizeof(long long) 也是 8。但这是一个真正的 64 位宽类型,并且具有完整的 64-位范围而不是 40 位。

更新

回到“39 位”的例子。

由于 6.2.8.1 要求所有完整类型的对齐是“字节”的整数倍,如果 CHAR_BIT 为 8,则必须将 39 位整数填充到至少 40 位或更大, 所以sizeof这样的类型必须是大于等于5的整数。

关于c - 是否保证每个 C 数据类型的大小都是字节的整数倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37750003/

相关文章:

c++ - 地震 2 md2 文件格式(理论)

C 指针差异 Char Int

c - 使用未命名管道发送信息

c - 使用 OpenMP 优化循环后没有性能提升

c - 需要在 C 中包含库吗?

c - 为什么 C11 全局和局部静态断言的行为不同?

c - &((struct name *)NULL -> b) 会导致 C11 中的未定义行为吗?

c - 安全浮点除法

c - C、C99、ANSI C 和 GNU C 之间有什么区别?

我可以在语句后进行 MSVS 2013 标志声明吗?