我知道 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/