如何确定/测量位域的结构大小?

Jag*_*gan 37 c bit-fields

#include <stdio.h>

typedef struct size
{
        unsigned int a:1;
        unsigned int b:31;
        unsigned int c:1;
} mystruct;

int main()
{
        mystruct a;
        printf("%d", sizeof(a));
        return 0;
}
Run Code Online (Sandbox Code Playgroud)
  • int b:31,输出为8.
  • int b:1,输出为4.
  • int b:32,输出为12.

有人能解释一下这个原因吗?

MdT*_*MdT 42

这是重要的顺序.以下代码将给出输出:8

#include<stdio.h>

typedef struct size
{
        unsigned int b:32;
        unsigned int a:1;
        unsigned int c:1;
}mystruct;

int main(int argc, char const *argv[])
{
        mystruct a;
        printf("\n %lu \n",sizeof(a));
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

unsigned int是一个32位整数,占用4个字节.内存在内存中连续分配.


选项1:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:31;      // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Second 4 bytes are allocated
Run Code Online (Sandbox Code Playgroud)

输出:8


选项2:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:32;      // Will NOT get accomodated in the First 4 bytes, Second 4 bytes are allocated
unsigned int c:1;       // Will NOT get accomodated in the Second 4 bytes, Third 4 bytes are allocated
Run Code Online (Sandbox Code Playgroud)

产量:12


选项3:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:1;       // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Will get accomodated in the First 4 bytes
Run Code Online (Sandbox Code Playgroud)

产量:4


选项4:

unsigned int b:32;      // First 4 bytes are allocated
unsigned int a:1;       // Second 4 bytes are allocated
unsigned int c:1;       // Will get accomodated in the Second 4 bytes
Run Code Online (Sandbox Code Playgroud)

输出:8

  • 在我看来,这应该是公认的答案. (3认同)

Ste*_*sop 29

你不知道你是否知道什么是bitfields,但我会假设你这样做.

在您的实现上,显然unsigned int是一个32位整数,占用4个字节.这解释了第一个和第二个例子.显然,总共33位的3个位域不适合单个unsigned int,因此在第一个示例中需要8个字节.总共3位的3个位域肯定适合于a unsigned int,因此在第二个例子中只有4个字节.

此外,位域不能跨越多个整数.这是第三个例子.我不记得这是标准的要求,还是实施的细节.无论哪种方式,因为b是32位的,它填补了整个unsigned int自身,迫使双方ac占据自己的unsigned int,之前和中间的一个之后.因此,12个字节.


Dig*_*oss 10

对准

编译器将结构的大小四舍五入为32位,每个对象的大小可以尝试引用32位,同时它保留了位字段的顺序.

因此,如果中间有一个32位项,每侧有一个1位项,则需要分配3个32位字,因此:12个字节.

对于另外两种情况,这只是一个问题,即你的位域序列可以打包到多少32位对象,同时仍保留字段顺序.


yua*_*uan 9

根据Steve jessop的回答,只是为了通过添加一些可能有用的文件来实现他的答案.

结构或联合的成员可以具有除可变修改类型之外的任何完整对象类型.此外,可以声明成员由指定数量的位组成(包括符号位,如果有的话).这样的成员称为位字段,其宽度前面有冒号

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

在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址.指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.结构对象中可能存在未命名的填充,但不是在其开头.

--ISO/IEC 9899:201x 6.7.2.1