40
#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;
}
  • int b:31输出为 8。
  • int b:1输出为 4。
  • int b:32输出为 12。

有人可以解释这个原因吗?

4

4 回答 4

54

重要的是顺序。以下代码将给出输出: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;
}

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

输出: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

输出: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

输出: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

输出:8

于 2013-04-21T08:26:12.020 回答
31

你不会说你是否知道位域是什么,但我假设你知道。

在您的实现中,显然unsigned int是一个 32 位整数,占用 4 个字节。这说明了第一个和第二个示例。显然,总共 33 位的 3 个位域不适合单个unsigned int,因此在第一个示例中需要 8 个字节。总共 3 位的 3 个位域确实适合unsigned int,因此在第二个示例中只有 4 个字节。

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

于 2010-11-09T02:32:41.873 回答
11

根据史蒂夫杰索普的回答,只是为了通过添加一些可能有帮助的文件来完成他的回答。

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

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

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

——ISO/IEC 9899:201x 6.7.2.1

于 2012-12-23T04:06:53.273 回答
10

结盟

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

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

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

于 2010-11-09T02:33:37.787 回答