这是一个主观问题,“为什么规范会这样说?” 但我会全力以赴。
函数中的变量通常具有“自动”存储,而不是其他持续时间之一(静态持续时间、线程持续时间和分配的持续时间)。
在结构中,您明确定义了某个对象的内存布局。但是在函数中,编译器会以某种未指定的方式自动为您的变量分配存储空间。x
这里有一个问题:堆栈上占用了多少字节?
// sizeof(unsigned) == 4
unsigned x;
它可能占用 4 个字节,也可能占用 8 个字节,或 12 个字节,或 0 个字节,或者它可以同时放在三个不同的寄存器中,或者堆栈和一个寄存器,或者它可以在堆栈上获得四个位置.
关键是编译器正在为您进行分配。由于您没有进行堆栈布局,因此不应指定位宽。
扩展讨论:位域实际上有点特殊。该规范规定相邻的位域被打包到同一个存储单元中。位域实际上不是对象。
您不能sizeof()
使用位字段。
您不能malloc()
使用位字段。
您不能&addressof
使用位字段。
所有这些事情你都可以用 C 中的对象来做,但不能用位域来做。位域是一种特殊的东西,专为结构而设计,其他任何地方都没有。
关于int24_t
(更新):它适用于某些架构,但不适用于其他架构。它甚至没有一点便携性。
typedef struct {
int x : 24 __attribute__((packed));
} int24_t;
在 Linux ELF/x64、OS X/x86、OS X/x64 sizeof(int24_t) == 3
、. 但在 OS X/PowerPC 上,sizeof(int24_t) == 4
.
注意 GCC 为加载生成的代码int24_t
基本上等同于:
int result = (((char *) ptr)[0] << 16) |
(((unsigned char *) ptr)[1] << 8) |
((unsigned char *)ptr)[2];
它是 x64 上的 9 条指令,仅用于加载单个值。