为什么普通变量不允许使用位域?

qwe*_*rtz 4 c gcc struct unions bit-fields

我想知道为什么bitfields与unions/structs一起工作,但是没有像int或那样的普通变量short.
这有效:

struct foo {
    int bar : 10;
};
Run Code Online (Sandbox Code Playgroud)

但这失败了:

int bar : 10; // "Expected ';' at end of declaration"
Run Code Online (Sandbox Code Playgroud)

为什么此功能仅在联合/结构中可用而不在变量中?技术不一样吗?


编辑:

如果允许,你可以创建一个3字节的变量,而不是每次都使用struct/union成员.这就是我对结构的看法:

struct int24_t {
    int x : 24 __attribute__((packed));
};

struct int24_t var; // sizeof(var) is now 3
// access the value would be easier:
var.x = 123;
Run Code Online (Sandbox Code Playgroud)

Die*_*Epp 7

这是一个主观问题,"为什么规范说这个?" 但我会试一试.

函数中的变量通常具有"自动"存储,而不是其他持续时间之一(静态持续时间,线程持续时间和分配的持续时间).

在结构中,您明确定义某个对象的内存布局.但是在函数中,编译器会自动以某种未指定的方式将存储分配给变量.这是一个问题:x堆栈上占用了多少字节?

// sizeof(unsigned) == 4
unsigned x;
Run Code Online (Sandbox Code Playgroud)

它可能占用4个字节,或者它可能占用8个,12个或0个,或者它可以同时放在三个不同的寄存器中,或者堆栈和寄存器,或者它可以在堆栈上获得四个位置.

关键是编译器正在为您进行分配.由于您没有进行堆栈布局,因此不应指定位宽.

扩展讨论: Bitfield实际上有点特殊.规范声明相邻的位域被打包到同一个存储单元中.位域实际上不是对象.

  1. 你不能sizeof()有点野外.

  2. 你不能malloc()有点野外.

  3. 你不能&addressof有点野外.

所有这些都可以用C语言中的对象完成,但不能用位域.Bitfields是一种特殊的东西,仅用于结构而不是其他任何地方.

关于int24_t(更新):它适用于某些体系结构,但不适用于其他体系结构.它甚至没有轻微的便携性.

typedef struct {
    int x : 24 __attribute__((packed));
} int24_t;
Run Code Online (Sandbox Code Playgroud)

在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];
Run Code Online (Sandbox Code Playgroud)

这是x64上的9条指令,只是为了加载一个值.