位域未在字节边界对齐的结构的大小

size of a struct with bitfields not aligned on byte boundary

这是我的程序

#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;
}

我原以为这个结构的大小相当大,但在我的机器上结果是 8,因为无符号是 4 个字节。现在我期望比这更多的原因是因为我希望 char b 在字节边界上,以便它在内存中正确对齐。现在我的猜测是编译器将 a、b、c 全部放在这 4 个字节中。我是 C 的新手,所以请多多包涵。我假设除了位字段之外的所有其他数据类型都必须是字节不正确的吗?如果它是正确的,我希望 a 取整个 unsigned int,b 取一个字节,然后填充 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 边界上,它使用 3 位 + 5 位填充(因为没有更多的位字段来用完剩余的位)。

b在字节2的边界上,它使用了一个完整的字节。

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

- int padding 在这里 -

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

一共8个字节...

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

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

我用一些值和 运行 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 输出中,底部行),但那里有一个额外的零字节。这是编译器的常见做法,因为他们试图以优化的方式对齐内存。