C中位域的存储器布局 - 无法理解输出

时间:2014-11-10 10:51:00

标签: c++ c memory output bit-fields

我有这段代码 - http://ideone.com/sXhWxf

#include <stdio.h>

int main(void) {

struct bitfield{
    unsigned a:5;
    unsigned c:5;
    unsigned b:6;
} bit = {1,3,3};

char *p = (char*)&bit;
printf("%d\n",*p);
p++;
printf("%d\n",*p);
// I assumed that the bits are laid out in the below order in the memory.
// Spaces are just for clarity
// 00001 00011 000011
// Also, I asumed that the 'char' will take 8 bits. But I can't understand output.
// According to me the output should be - 8 195 (considering the 1st 8 bits & 
// last eight bits for the printf statements)
return 0;

}

输出是 -

97
12

有人可以帮我详细了解这个输出吗? (请阅读代码中的评论)

另外,我在Wikipedia上发现了这句话,其中说“位字段的成员没有地址,因此不能与(&amp;)一元运算符的地址一起使用。 sizeof运算符可能不适用于位字段。“但我可以访问'bit'变量的地址。那个怎么样?我没有正确解释声明吗?请指导我。

3 个答案:

答案 0 :(得分:3)

假设目标机器上的整数是32位,编译器已经像这样布局了bit结构:

bit 31                            bit 0
|                                 |
xxxxxxxxxxxxxxxx bbbbbb ccccc aaaaa

其中x位未使用。

使用a=1, c=3, b=3,这变为

0000000000000000 000011 00011 00001

拆分为字节:

00000000 00000000 00001100 01100001

十进制:

0 0 12 97

当存储为小端整数时,字节顺序为97 12 0 0,这解释了您的输出。

关于你的第二个问题:你正在采用bit结构的地址,而不是其任何位域。 char *p = (char*)&bit.a;无效。

答案 1 :(得分:0)

你试图访问结构的地址而不是位域,这就是为什么你能够访问char p =(char )&amp; bit;

你不能做这样的事情 p =(char )&amp;(bit.a);

现在谈到实际的一点:

建议不要使用地址访问位字段,因为内存中位字段的打包取决于很多参数。

答案 2 :(得分:0)

借用此处的另一个答案(Memory layout of struct having bitfields),C规范并未对位域的排序做出任何保证:

  

实现可以分配足够大的任何可寻址存储单元来保存位域。如果剩余足够的空间,则紧跟在结构中的另一个位字段之后的位字段将被打包到相同单元的相邻位中。如果剩余的空间不足,则是否将不适合的位域放入下一个单元或重叠相邻单元是实现定义的。单元内的位域分配顺序(高阶到低阶或低阶到高阶)是实现定义的。

在这种情况下,让我们看看你的例子中的输出。

97转换为01100001.如果我们分开,我们可以看到我们的成员为... 011 00001. 12转换为000011 00,这构成了我们数据结构的其余部分。正如您所假设的那样,编译器将每个变量首先打包到内存中的最低位而不是最高位。

由于这是实现定义的,因此除非您确切知道编译器将对代码执行的操作,否则不建议使用它。

有关更多信息和示例,请参阅此处:C/C++: Force Bit Field Order and Alignment