C 包含位字段的结构的大小在不同的编译器上是不同的

C 包含位字段的结构的大小在不同的编译器上是不同的,c,visual-studio,gcc,C,Visual Studio,Gcc,我在VS和GCC上运行了下面的程序 #include <stdio.h> int main(void) { struct bitfield { unsigned a : 3; char b; unsigned c : 5; int d; }bit; printf("Size = %d\n", sizeof(bit)); return 0; } #包括 内部主(空) { 结构

我在VS和GCC上运行了下面的程序

#include <stdio.h>

int main(void)
{
    struct bitfield
    {
        unsigned a : 3;
        char b;
        unsigned c : 5;
        int d;
    }bit;

    printf("Size = %d\n", sizeof(bit));

    return 0;
}
#包括
内部主(空)
{
结构位域
{
未签名a:3;
字符b;
无符号c:5;
int d;
}比特;
printf(“大小=%d\n”,大小(位));
返回0;
}
令我惊讶的是,VS给出16作为
sizeof
结构,GCC给出12

我的理解是,编译器试图将
a
char b
c
分配到一行(Bank0、Bank1、Bank2、Bank3),并将
int d
分配到另一行。这似乎表明结构的大小应该是8字节(假设是32位系统)


有人能解释这些结果吗?我在64位计算机上运行。

由于您的系统具有64位体系结构,大多数编译器将以8字节填充。
Gcc在其当前版本中仍然填充4个字节
此外,结构填充完全依赖于编译器。在“c”代码中有许多未定义的行为,比如使用一元增量(pre/post)、填充、内存映射等,这些行为完全依赖于编译器和m/c。因此,实际上没有这样的解释。
另外,在系统上运行以下代码。在这种情况下,VS应为o/p 24和GCC 16

#include <stdio.h>

int main(void)
{
    struct bitfield
    {
        unsigned a : 3;
        unsigned c : 5;
        int d;
        char b;
    }bit;

    printf("Size = %d\n", sizeof(bit));

    return 0;
}
#包括
内部主(空)
{
结构位域
{
未签名a:3;
无符号c:5;
int d;
字符b;
}比特;
printf(“大小=%d\n”,大小(位));
返回0;
}

编译器只需将结构中相邻声明的位字段打包到同一个“可寻址存储单元”(给定32位CPU,在本例中可能是32位的块)。您在它们之间显示了一个字符,因此编译器可以随意分配结构

通常,标准对位字段的规定非常糟糕,因此完全不可移植且不可预测。未指定位的分配顺序。未指定哪个位是MSB。未指定对齐方式。未指定位字段是否“跨”于“存储单元”。等等

此外,结构可以在任何位置包含填充字节


更好的办法是根本不使用位字段,而是使用按位运算符。

首先,告诉我编译器上sizeof(int)的o/p我觉得它将是8,而不是4(如您所预期),因为m/c是64位的,编译器也是64位的。这取决于编译器。对于VS可能会有所帮助。对于如何填充此结构,您确实无法做出任何假设。在这方面,每个编译器都可以自由地做任何事情,只要元素都正确对齐并且顺序正确。