可能重复:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
我试图了解位字段的概念。 但我无法找到CASE III中以下结构的大小为8个字节的原因。
struct B
{
unsigned char c; // +8 bits
} b;
的sizeof(B); //输出:1(因为unsigned char在我的系统上占用1个字节)
struct B
{
unsigned b: 1;
} b;
sizeof(b); // Output: 4 (because unsigned takes 4 bytes on my system)
struct B
{
unsigned char c; // +8 bits
unsigned b: 1; // +1 bit
} b;
sizeof(b); // Output: 8
我不明白为什么案例III的输出为8.我期待1(字符)+4(无符号)= 5.
答案 0 :(得分:7)
您可以使用offsetof
检查结构的布局,但它将是以下内容:
struct B
{
unsigned char c; // +8 bits
unsigned char pad[3]; //padding
unsigned int bint; //your b:1 will be the first byte of this one
} b;
现在很明显(在一个32位的拱门中)sizeof(b)
将是8
,不是吗?
问题是,为什么3个字节的填充,而不是更多或更少?
答案是结构中字段的偏移与字段本身的类型具有相同的对齐要求。在您的体系结构中,整数是4字节对齐的,因此offsetof(b, bint)
必须是4的倍数。它不能是0,因为之前有c
,所以它将是4.如果是字段{{ 1}}从偏移量4开始,长度为4个字节,然后结构的大小为8。
另一种看待它的方法是结构的对齐要求是其任何字段中最大的,因此这个bint
将是4字节对齐的(因为它是你的位字段)。但是一个类型的大小必须是对齐的倍数,4是不够的,所以它将是8。
答案 1 :(得分:3)
答案 2 :(得分:2)
Char定义为一个字节。 int是32位系统上的4个字节。并且结构被填充额外的4。
有关填充的一些解释,请参阅http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86
答案 3 :(得分:1)
为了保持对内存的访问对齐,编译器会添加填充,如果打包结构,它将不会添加填充。
答案 4 :(得分:1)
结构的对齐和总大小是平台和编译器特定的。你不能不期望在这里得到直截了当和可预测的答案。编译器总能有一些特别的想法。例如:
struct B
{
unsigned b0: 1; // +1 bit
unsigned char c; // +8 bits
unsigned b1: 1; // +1 bit
};
编译器可以将字段b0和b1合并为一个整数,也可以不合并。这取决于编译器。有些编译器有控制它的命令行键,有些编译器没有。其他例子:
struct B
{
unsigned short c, d, e;
};
由编译器打包/不打包此结构的字段(假设32位平台)。结构的布局可以在DEBUG和RELEASE构建之间有所不同。
我建议只使用以下模式:
struct B
{
unsigned b0: 1;
unsigned b1: 7;
unsigned b2: 2;
};
当您拥有共享相同类型的位字段序列时,编译器会将它们放入一个int中。否则各个方面都可以启动。还要考虑到在一个大项目中你编写一段代码,其他人会编写并重写makefile;将代码从一个dll移动到另一个dll。此时将设置和更改编译器标志。 99%的可能性,这些人不知道你的结构的对齐要求。他们甚至都不打开你的文件。
答案 5 :(得分:1)
我再看看这个,这就是我找到的。
struct B { unsigned c: 8; unsigned b: 1; }b; printf("%lu\n", sizeof(b));
打印4这是一个简短的;
您正在将位字段与常规struct元素混合使用。
BTW,位字段被定义为:“在一个主题实现定义的存储单元中的一组相邻的位”所以,我甚至不确定':8'是做什么的你要。这似乎不符合比特字段的精神(因为它不再是一点点)