在字节边界上没有对齐的位域的结构的大小

时间:2017-07-30 19:37:34

标签: c struct memory-alignment

这是我的程序

public date: Date;

constructor() {
  this.date = new Date();
}

public dateForward = () => this.date.setDate(this.date.getDate() + 1);

public dateBack = () => this.date.setDate(this.date.getDate() - 1);

我期待这个结构的大小非常多,但它在我的机器上是8,因为unsigned是4个字节。我之所以期待更多的原因是因为我希望#include <stdio.h> #include <string.h> #include <stdlib.h> int main() { struct bitfield { unsigned a:3; char b; unsigned c:5; int d; }bit; printf("%lu \n",sizeof(bit)); return 0; } 位于字节边界上,以便它在内存中正确对齐。现在我的猜测是编译器将a,b,c全部放在这4个字节中。我是C的新手,所以请耐心等待。我的假设是除了位字段之外的所有其他数据类型必须在字节上不正确吗?如果它是正确的,我希望,char b取整个unsigned int,a取一个字节然后填充3个字节,然后等等。我在这里缺少什么?

2 个答案:

答案 0 :(得分:3)

我似乎无法理解冲突。

你基本上有:

struct bitfield {
     unsigned a:3;
     unsigned padding1:5;
     char b;
     unsigned c:5;
     unsigned padding2:3;
     unsigned padding3:8;
     int d;
}bit;

a在字节1边界上,它使用三位+5位填充(因为没有更多的位字段用于剩余位)。

b在字节2边界上,它使用整个字节。

c在字节3边界上,它使用5位+ 3位填充(因为没有更多的位字段用于剩余位)。

- int padding来到这里 -

d位于int边界(您机器上的4个字节)。它使用1个字节用于填充+ 4个字节用于数据。

所有这些,8个字节......

...尽管正如@ JonathanLeffler在评论中指出的那样,这是特定于实现的,并不意味着每个编译器的行为都相同。

答案 1 :(得分:2)

您通常以这种方式对齐位域,它们共享一个字节。当您在位域之间放置另一个变量时,未使用的位最终会使用您不需要但仍然需要空间的内存空间。

我用一些值测试了你的代码并在gdb中运行程序。

bit.a = 1;
bit.b = 'a';
bit.c = 4;
bit.d = 1337;

在gdb中打印内存时,输出如下所示

(gdb) x/8b &bit
0x7fffffffe118: 00000001    01100001    00000100    00000000
                00111001    00000101    00000000    00000000

因此我们看到第一个字节完全用于字段a,尽管它只使用3位。字段b中的字符a也占用一个字节。第三个字节(00000100)匹配字段c的值4,这里有趣的是:

然后你有一个使用4个字节的整数(在最后4个字节,最后一行的gdb输出中),但那里有一个额外的零字节。这是编译器的常见实践,因为它们试图以优化的方式对齐内存。