2

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

任何帮助都非常受欢迎。

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
4

2 回答 2

8

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        |
+----+----+----+----+----+----+----+----+

这显然是您预期的行为。

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

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

于 2012-04-12T18:13:50.503 回答
8

几乎所有关于位域的东西都是实现定义的。尤其是单位中的位顺序。

(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如果您认为最左边的位是最低有效位。

于 2012-04-12T16:49:52.040 回答