我知道sizeof(char)将始终为1,并且这是以字节为单位的,并且一个字节可以是任意数量的位(我相信任何位数大于或等于8,但不是积极的)。
我也经常看到提及C数据类型大小如何根据它们的大小之间的关系来指定的引用,例如“sizeof(int)< = sizeof(long)”。
我的问题基本上是:“sizeof(int)”在一个字节为8位且int为39位(或其他一些不能被CHAR_BIT整除的值)的系统上进行评估。
我的猜测是sizeof()返回存储类型所需的最小字节数,因此它将向上舍入到下一个字节。因此,在我的39位int示例中,sizeof(int)的结果为5。
这是对的吗?
此外,是否有一种简单的方法可以确定特定类型可以容纳的100%可移植的位数,并且不需要包含任何标头?对于学习体验而言,这比实际应用更多。我会在实践中使用stdint类型。我想的可能就是声明变量并将其初始化为~0,然后循环并左移它直到它为零。
谢谢!
答案 0 :(得分:3)
人们经常无法理解的是,在C中,sizeof
和“宽度”之间存在明显的区别。
“width”更多关于二进制表示,范围,溢出/环绕行为。你说无符号整数类型是16位宽,那么你的意思是它包围在65535.
但是sizeof
只关心存储。因此,通过允许sizeof(T[n])==sizeof(T)*n
包含填充来维护sizeof
。
由于这个原因,尝试在sizeof
类型和类型的算术行为之间找到连接是没有意义的:类型可以有一定的范围,但可以占用它想要的任何存储空间。
回答你的问题(“如果在8位字符机器上使用39位int怎么办?”)我想以TI C6400 +为例,因为它有一个40位{{1}和8位字符,非常接近。
TI C6400 +是一个字节可寻址机器,因此它必须将8位字节定义为long
。
它还有一个40位整数类型,因为ALU可以在40位整数上运行,并且它们将其定义为char
。
你会认为long
应该是5,对吗?
嗯,它可以,但是这个CPU也不支持非对齐加载,所以出于性能原因,这个sizeof(long)
类型默认对齐为8字节边界而不是5字节,然后每个{ {1}}有3个字节的填充(在内存和寄存器级别,因为它在CPU中也需要一对GPR),然后自然long
变为8。
有趣的是,C6400 + C实现还提供long
,sizeof(long)
也是8.但这是一个真正的64位宽类型,并且具有完整的64位范围而不是40位。
<强>更新强>
回到“39位”的情况。
由于6.2.8.1要求所有完整类型的对齐是“bytes”的整数倍,因此如果long long
为8,则必须将39位整数填充到至少40位或更大,因此{ {1}}此类型必须是大于或等于5的整数。
答案 1 :(得分:1)
6.2.6类型表示
6.2.6.1概述
49)使用二进制数字0和1的整数的位置表示,其中包含值 由连续位表示的是加法的,以1开始,并乘以连续的积分 2的幂,除了位置最高的位。 (改编自美国国民 信息处理系统字典。)一个字节包含
- 除本条款所述外,所有类型的陈述均未指明。
- 除了位字段外,对象由一个或多个字节的连续序列组成, 其数量,顺序和编码是明确指定的 实现定义。
- 存储在无符号位域和
unsigned char
类型对象中的值应为 使用纯二进制表示法表示。 49)- 存储在任何其他对象类型的非位字段对象中的值由
n × CHAR_BIT
组成 位,其中n
是该类型对象的大小,以字节为单位。该值可以复制到 类型unsigned char [n]
的对象(例如,memcpy
);得到的字节集是 称为值的对象表示。存储在位字段中的值由m
位组成, 其中m
是为位字段指定的大小。对象表示是m
的集合 比特字段包含在保持它的可寻址存储单元中。两个值(其他 比NaNs)具有相同的对象表示比较相等,但比较的值 等于可以具有不同的对象表示。CHAR_BIT
位,以及值 类型unsigned char
的范围从0
到2^CHAR_BIT − 1
。
我的问题基本上是:“sizeof(int)”在一个字节为8位且int为39位(或其他一些不能被CHAR_BIT整除的值)的系统上评估为什么。
实现必须将CHAR_BIT
大小的存储单元映射到奇数大小的单词上,以满足上述要求,可能会带来显着的性能损失。 39位字最多可容纳4个8位或9位存储单元,因此sizeof (int)
可能评估为4。
或者,实现者可以简单地判断它不值得麻烦并将CHAR_BIT
设置为39; 所有(包括单个字符)占用一个或多个完整字,根据类型最多留下31位。
过去曾有过这种事情的真实例子。其中一个旧的DEC PDP(我想说PDP-8,也许是PDP-11?)使用36位字和7位ASCII字符值; 5个字符可以存储在一个单词中,其中一个字节未使用。所有其他类型都占据了一个完整的词。如果实现将CHAR_BIT
设置为9,则可以将CHAR_BIT
大小的存储单元干净地映射到36位字,但同样,如果硬件每个单词预计5个字符。
答案 2 :(得分:0)
每个C数据类型的大小是否保证是字节的倍数?
是。即使在CHAR_BIT
= 32的系统上,表示数据类型所需的位数小于struct foo { unsigned int bar : 1};
,例如int16_t
或CHAR_BIT
。
sizeof(char) = 1 (guaranteed)
CHAR_BIT >= 8 ( = 8 on posix compliant system)
sizeof(anything else) = k * sizeof(char) = k where k is a whole number
来自 6.5.3.4 sizeof和_Alignof运算符
sizeof运算符产生其操作数的大小(以字节为单位) 可以是表达式或类型的带括号的名称。大小是 根据操作数的类型确定。结果是整数。 [...]
为了增加您的困惑,在CHAR_BIT = 32
的计算机上,sizeof(int16_t)
将为1,因此sizeof(int32_t)
也是如此,您实际上最终可能会分配更多的内存字节如果您使用malloc(sizeof(int16_t) * n)
代替malloc(sizeof(int16_t[n])
,则需要(我不确定)。