C语言 如何确定/测量具有位字段的结构的大小?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4129961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How is the size of a struct with Bit Fields determined/measured?
提问by Jagan
#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;
}
- With
int b:31, the output is 8. - With
int b:1, the output is 4. - With
int b:32, the output is 12.
- 使用
int b:31,输出为 8。 - 使用
int b:1,输出为 4。 - 使用
int b:32,输出为 12。
Can somebody explain the reason for this?
有人可以解释一下原因吗?
采纳答案by Steve Jessop
You don't say whether you know what bitfields are, but I'll assume you do.
你没有说你是否知道位域是什么,但我假设你知道。
On your implementation, evidently unsigned intis a 32 bit integer, occupying 4 bytes. This accounts for the first and second examples. Clearly 3 bitfields totalling 33 bits don't fit into a single unsigned int, hence the need for 8 bytes in the first example. 3 bitfields totalling 3 bits certainly do fit into an unsigned int, hence only 4 bytes in the second example.
在您的实现中,显然unsigned int是一个 32 位整数,占用 4 个字节。这说明了第一个和第二个示例。显然,总共 33 位的 3 个位域不适合单个unsigned int,因此在第一个示例中需要 8 个字节。总共 3 个位的 3 个位域确实适合一个unsigned int,因此在第二个示例中只有 4 个字节。
Furthermore, a bitfield cannot span multiple integers. This accounts for the third example. I can't remember whether that's a requirement of the standard, or just a detail of your implementation. Either way, since bis 32 bits, it fills a whole unsigned inton its own, forcing both of aand cto occupy their own unsigned int, before and after the middle one. Hence, 12 bytes.
此外,位域不能跨越多个整数。这说明了第三个例子。我不记得这是标准的要求,还是您的实现细节。无论哪种方式,由于b是 32 位,它unsigned int自己填充一个整体,迫使两者a和c占据自己的unsigned int,在中间之前和之后。因此,12 个字节。
回答by MdT
It is the order that matters. The following code will give Output: 8
重要的是顺序。以下代码将给出输出: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 is a 32 bit integer, occupying 4 bytes. Memory is allocated contiguously in memory.
Unsigned int 是一个 32 位整数,占用 4 个字节。内存在内存中连续分配。
Option 1:
选项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
Output: 8
输出:8
Option 2:
选项 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
Output: 12
输出:12
Option 3:
选项 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
Output: 4
输出:4
Option 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
Output: 8
输出:8
回答by DigitalRoss
Alignment
结盟
The compiler is rounding the size of the structure to 32 bits, the size of each object it may try to reference to 32 bits, and at the same time it is preserving the order of your bit fields.
编译器将结构的大小四舍五入为 32 位,它可能尝试引用的每个对象的大小为 32 位,同时它保留了位域的顺序。
So if you have a 32-bit item in the middle and 1-bit items on each side, that's 3 32-bit words to allocate and so: 12 bytes.
因此,如果中间有一个 32 位项目,每侧有 1 位项目,则需要分配 3 个 32 位字,因此:12 个字节。
For the other two cases, it's just a question of how few 32-bit objects your bitfield sequence can be packed into, while still preserving field order.
对于其他两种情况,问题只是位域序列可以装入多少个 32 位对象,同时仍保留字段顺序。
回答by yuan
According to Steve jessop's answerjust to fulfill his answer by adding some documents which may help.
根据Steve jessop 的回答,只是为了通过添加一些可能有帮助的文件来完成他的回答。
A member of a structure or union may have any complete object type other than a variably modified type.In addition, a member may be declared to consist of a specified number of bits (including a sign bit, if any). Such a member is called a bit-fieldits width is preceded by a colon
An implementation may allocate any addressable storage unit large enough to hold a bit- field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined.The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.
Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.
结构或联合的成员可以具有除可变修改类型之外的任何完整对象类型。此外,可以声明成员由指定数量的位(包括符号位,如果有)组成。这样的成员称为位域,其宽度前面有一个冒号
一个实现可以分配任何足够大的可寻址存储单元来保存一个位域。如果剩余足够的空间,紧跟在结构中另一个位域之后的位域应被打包到同一单元的相邻位中。如果剩余空间不足,则不适合的位字段是否放入下一个单元或与相邻单元重叠是实现定义的。单元内位域的分配顺序(高阶到低阶或低阶到高阶)是实现定义的。可寻址存储单元的对齐方式未指定。
在结构对象中,非位域成员和位域所在的单元的地址按它们声明的顺序增加。指向结构对象的指针,经过适当转换,指向其初始成员(或者如果该成员是位域,则指向它所在的单元),反之亦然。结构对象内可能有未命名的填充,但不是在其开头。
——ISO/IEC 9899:201x 6.7.2.1
——ISO/IEC 9899:201x 6.7.2.1

