以下C标准的所有章节号都来自这个特定的C11草案版本
段。 C11 第 3.19.4 节第 1 条规定:
陷阱表示
不需要表示对象类型值的对象表示
段。 C11 第 6.2.6.2 节第 1 条规定:
对于unsigned char以外的无符号整数类型,对象的位 表示应分为两组:值位和填充位(需要 不是后者中的任何一个)。 ...
段。 C11 第 6.5.3.4 节第 2 条规定:
sizeof 运算符产生其操作数的大小(以字节为单位),这可能是一个 表达式或类型的括号名称。大小由类型决定 操作数
假设地,假设我设计了一个 CPU 架构(浪费地)使用三个字节(24 位)来存储
uint16_t
(又名 short
)。这个浪费uint16_t
的范围还是[0, 65535]。它的最后两个字节是一个普通的uint16_t
,第一个字节是为所有可能的陷阱表示保留的。
为了简单起见,假设
uint16_t
只有在第一个字节是0000 0000
时才有效;如果第一个字节不是 uint16_t
.,则
0000 0000
未初始化(因此是陷阱表示)
问题是,对于我浪费的一个变量
short
:
uint16_t a = 123;
sizeof
的预期结果是什么?:
sizeof a;
更重要的是,应该使用C标准的哪一部分的哪一段来支持预期的结果?
sizeof 运算符的结果不依赖于存储在对象中的值。
正如你自己写的
sizeof 运算符产生其操作数的大小(以字节为单位),这 可以是表达式或带括号的类型名称。大小是 由操作数的类型决定
所以根据你的描述
假设,假设我设计了一个 CPU 架构 (浪费)使用三个字节
sizeof 运算符将返回 3,尽管类型名称会使用户感到困惑。
更真实的情况是结构。它们的数据成员之间可以有很多填充,并且考虑这些填充以确定必须为结构类型的对象分配多少内存。
还要考虑指针运算。如果你有一个像
这样的数组uint16_t a[2];
那么表达式
a + 1
必须指向数组的第二个元素。表达式的计算方式类似于( char * )a + sizeof( uint16_t )
。如果sizeof( uint16_t )
不等于3,你会得到一个不正确的值。
有两种可能的结果。 1 或 3。
在你设计的“奇废”系统中,我们不知道用于存储
char
的字节数。如果您决定为 char
使用 3 个字节,则答案为 1。如果您决定为 char
使用 1 个字节,则答案为 3.
一般答案是:
(bytes used for storing wasteful-uint16) / (bytes used for storing char)