我确实有一个带有位字段的结构。根据我的说法,它的结果是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个字节?
答案 0 :(得分:1)
int c:8;
表示您声明了一个大小为8位的bit-field
。由于32位系统上的alignemt通常为4个字节(= 32位),因此您的对象将显示为4个字节而不是2个字节(char + 8位)。
答案 1 :(得分:1)
来源: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的简化特性。相反,使用逐位运算符。逐位运算符和深入记录的位字段将生成相同的机器代码(未记录的位字段可以自由地生成相当任意的代码)。但是,逐位运算符可以保证在世界上任何编译器/系统上都能正常工作。