这个结构的大小如何是4字节

时间:2011-08-19 12:15:44

标签: c bit-fields

我确实有一个带有位字段的结构。根据我的说法,它的结果是2个字节但它的结果是4个。我已经在stackoverflow上读到了与此相关的一些问题但是无法与之相关我的问题。这是我有的结构

struct s{
char b;
int c:8;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}

如果int类型必须在其内存边界上,那么输出应该是8个字节,但它显示4个字节?

5 个答案:

答案 0 :(得分:1)

int c:8;表示您声明了一个大小为8位的bit-field。由于32位系统上的alignemt通常为4个字节(= 32位),因此您的对象将显示为4个字节而不是2个字节(char + 8位)。

答案 1 :(得分:1)

enter image description here

来源:http://geeksforgeeks.org/?p=9705

总之:它正在优化位的打包(这就是位字段的意思)尽可能最大化而不会影响对齐。

变量的数据对齐处理数据存储在这些库中的方式。例如,32位机器上int的自然对齐是4个字节。当数据类型自然对齐时,CPU会以最小读取周期取出它。

类似地,short int的自然对齐是2个字节。这意味着,一个短的int可以存储在银行0 - 银行1对或银行2 - 银行3对。 double需要8个字节,占用存储体中的两行。任何双重错位都会强制两个以上的读取周期来获取双数据。

请注意,双变量将在32位机器上的8字节边界上分配,并且需要两个存储器读取周期。在64位机器上,根据存储区数量,双变量将在8字节边界上分配,并且只需要一个存储器读周期。

因此,编译器将为每个结构引入对齐要求。它将是该结构中最大的成员。如果您从char中移除struct,则仍会获得 4个字节

struct中,char对齐1个字节。它后跟一个int位字段,对于整数,它是4字节对齐的,但是您定义了一个位字段。

8位= 1个字节。 Char可以是任何字节边界。所以Char + Int:8 = 2个字节。好吧,这是一个奇数字节边界,因此编译器增加了2个字节来维持4字节边界。

要使它为8个字节,您必须声明实际的int(4个字节)和char(1个字节)。那是5个字节。那是另一个奇数字节边界,所以struct被填充到 8个字节

我过去通常用来控制填充的是将填充符放在我的struct之间以始终保持4字节边界。所以,如果我有struct这样的话:

struct s {
    int id;
    char b;
};

我将按如下方式插入分配:

struct d {
    int id;
    char b;
    char temp[3];
}

这会给我一个大小为4字节+ 1字节+ 3字节= 8字节的struct!通过这种方式,我可以确保以我想要的方式填充struct,特别是如果我通过网络将其传输到某处。另外,如果我改变了我的实现(例如,如果我可能将此struct保存到二进制文件文件中,那么填充程序从一开始就存在,所以只要我保持我的初始结构,一切都很好!)

最后,您可以在C Structure size with bit-fields上阅读此帖子以获得更多解释。

答案 2 :(得分:0)

但是如果你指定c应该占用8位,它不是真正的int,是吗? c + b的大小为2个字节,但您的编译器将结构填充为4个字节。

答案 3 :(得分:0)

结构中字段的对齐取决于编译器/平台。 也许你的编译器使用16位整数来表示长度小于或等于16位的位域,也许它永远不会在小于4字节边界的任何位置上对齐结构。

结论:如果你想知道struct字段是如何对齐的,你应该阅读你正在使用的编译器和平台的文档。

答案 4 :(得分:0)

在通用的,与平台无关的C中,您永远不会知道结构/联合的大小,也不知道位字段的大小。编译器可以在struct / union / bit-field中的任何位置随意添加尽可能多的填充字节,除非是在第一个内存位置。

此外,编译器还可以自由地将任意数量的填充添加到位字段,并可以将它们放在任何喜欢的位置,因为哪个位是msb而lsb未定义为下进行。

当谈到位字段时,你会被C语言冷落,没有标准。您必须详细阅读编译器文档,以了解它们在特定平台上的行为方式,并且它们完全不可移植。

明智的解决方案是永远不要使用位字段,它们是C的简化特性。相反,使用逐位运算符。逐位运算符和深入记录的位字段将生成相同的机器代码(未记录的位字段可以自由地生成相当任意的代码)。但是,逐位运算符可以保证在世界上任何编译器/系统上都能正常工作。