位字段结构分配意外行为

我不知道为什么但位字段分配没有按预期工作。 可能只是一个愚蠢的事情,但我无法找到问题所在。

任何帮助都非常受欢迎。

typedef struct a { unsigned char a1 :1; unsigned char a2 :3; unsigned char a3 :2; unsigned char a4 :2; } __attribute__((packed)) mystruct; int main() { mystruct d; d.a1 = 0; d.a2 = 2; d.a3 = 1; d.a4 = 2; unsigned char *val = (unsigned char*) &d; printf("%02X \n", *val); printf("%02X \n", sizeof(hola)); exit(0); } 

返回输出:

 94 01 

预期产量:

 26 01 

关于位字段的几乎所有内容都是实现定义的。 特别是单位中的位顺序。

(C99,6.7.2.1p10)“单位内的位域分配顺序(从高位到低位或低位到高位)是实现定义的。”

在您的实现中,这些位首先存储在单元lsb(最低有效位)中,而不是首先存储在msb(最高有效位)中,如您所期望的那样。

你有的是:

 [a1.0] [a2.0] [a2.1] [a2.2] [a2.0] [a3.1] [a4.0] [a4.1] 0 0 1 0 1 0 0 1 bit 0 - bit 7 lsb - msb 

如果你认为最左边的位是最低有效位,则为0x94

ASCII艺术:

  MSB LSB +----+----+----+----+----+----+----+----+ |a4.1|a4.0|a3.1|a3.0|a2.2|a2.1|a2.0| a1 | +----+----+----+----+----+----+----+----+ | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | +----+----+----+----+----+----+----+----+ | 0x9 | 0x4 | +----+----+----+----+----+----+----+----+ 

如上所述,行为是实现定义的; 这是组织数据的两种合法方式之一,似乎是您机器上选择的格式。 替代行为是。

  MSB LSB +----+----+----+----+----+----+----+----+ | a1 |a2.2|a2.1|a2.0|a3.1|a3.0|a4.1|a4.0| +----+----+----+----+----+----+----+----+ | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | +----+----+----+----+----+----+----+----+ | 0x2 | 0x6 | +----+----+----+----+----+----+----+----+ 

这显然是你期望的行为。

由于它是实现定义的,因此您可以查看手册并查找编译器的function,因为编译器必须记录其行为。

如果您需要担心可移植性,则需要考虑如何组织结构定义,使其按照您在所使用的每个平台上工作的方式工作。