如何确定/测量具有位字段的结构的大小? #包括 typedef结构大小 { 无符号整数a:1; 无符号整数b:31; 无符号整数c:1; }我的结构; int main() { 我的结构a; printf(“%d”,sizeof(a)); 返回0; } 使用intb:31,输出为8 使用intb:1,输出为4 使用intb:32,输出为12

如何确定/测量具有位字段的结构的大小? #包括 typedef结构大小 { 无符号整数a:1; 无符号整数b:31; 无符号整数c:1; }我的结构; int main() { 我的结构a; printf(“%d”,sizeof(a)); 返回0; } 使用intb:31,输出为8 使用intb:1,输出为4 使用intb:32,输出为12,c,bit-fields,C,Bit Fields,有人能解释一下原因吗?你没有说你是否知道位字段是什么,但我假设你知道 在您的实现中,显然unsigned int是一个32位整数,占用4个字节。这就解释了第一个和第二个例子。显然,总计33位的3位字段不适合单个无符号int,因此在第一个示例中需要8个字节。总计3位的3位字段确实适合无符号int,因此在第二个示例中只有4个字节 此外,位字段不能跨越多个整数。这就是第三个例子。我不记得这是标准的要求,还是只是实现的细节。无论哪种方式,由于b是32位,它自己填充整个无符号int,迫使a和c在中间的in

有人能解释一下原因吗?

你没有说你是否知道位字段是什么,但我假设你知道

在您的实现中,显然
unsigned int
是一个32位整数,占用4个字节。这就解释了第一个和第二个例子。显然,总计33位的3位字段不适合单个
无符号int
,因此在第一个示例中需要8个字节。总计3位的3位字段确实适合
无符号int
,因此在第二个示例中只有4个字节

此外,位字段不能跨越多个整数。这就是第三个例子。我不记得这是标准的要求,还是只是实现的细节。无论哪种方式,由于
b
是32位,它自己填充整个
无符号int
,迫使
a
c
在中间的int之前和之后占据它们自己的
无符号int
。因此,需要12个字节。

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

这样,如果中间有一个32位的项目和每一方的1位项目,那就是要分配3个32位字,因此:12个字节。

对于其他两种情况,这只是一个问题,即在保持字段顺序的同时,您的位字段序列可以打包到多少32位对象中。

根据just的回答,添加一些文档可能会有所帮助

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

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

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


--ISO/IEC 9899:201x 6.7.2.1重要的是顺序。以下代码将给出输出:8

#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;
}
产出:8

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

备选案文2:

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
产出:12


备选案文3:

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
产出:4


备选案文4:

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

输出:8

如果您想知道64位机器何时比32位机器占用的空间少(或者至少比32位机器占用的空间少),那么这就是一个例子。@JonathanLeffler:您确定吗?x64linux/ELF上的GCC表示,(1,32,1)案例的大小为12。我相信影响这种结构规模的唯一因素是基础类型的规模,在这种情况下,它是
unsigned int
@DietrichEpp:ISO/IEC 9899:2011§6.7.2.1结构和联合说明符:指定位字段宽度的表达式应为整数常量表达式,其非负值不超过将指定为冒号和省略表达式。我认为这支持你的论点……但如果我们要找到一台ILP64机器(而不是通常的LP64机器),那么我会绕着它转。我认为,这应该是公认的答案。位字段的位置决定大小,因为它会导致填充。同样,建议结构的顶部具有最高。最大元素的顶部具有最佳/最小填充
#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;
}