Size of structure with a char, a double, an int and a t
当我只运行代码片段时
1 2 3 4 5 | int *t; std::cout << sizeof(char) << std::endl; std::cout << sizeof(double) << std::endl; std::cout << sizeof(int) << std::endl; std::cout << sizeof(t) << std::endl; |
它给了我这样一个结果:
1 2 3 4 | 1 8 4 4 |
总数:17。
但是当我测试包含这些数据类型的结构sizeof时,它给了我24个,我很困惑。另外7个字节是什么?
这是密码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <iostream> #include <stdio.h> struct struct_type{ int i; char ch; int *p; double d; } s; int main(){ int *t; //std::cout << sizeof(char) <<std::endl; //std::cout << sizeof(double) <<std::endl; //std::cout << sizeof(int) <<std::endl; //std::cout << sizeof(t) <<std::endl; printf("s_type is %d byes long",sizeof(struct struct_type)); return 0; } |
编辑
我像这样更新了我的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <iostream> #include <stdio.h> struct struct_type{ double d_attribute; int i__attribute__(int(packed)); int * p__attribute_(int(packed));; char ch; } s; int main(){ int *t; //std::cout<<sizeof(char)<<std::endl; //std::cout<<sizeof(double)<<std::endl; //std::cout<<sizeof(int)<<std::endl; //std::cout<<sizeof(t)<<std::endl; printf("s_type is %d bytes long",sizeof(s)); return 0; } |
现在它显示了16个字节。它是好的,还是丢失了一些重要的字节?
一些成员之间有一些未使用的字节,以保持对齐正确。例如,为了提高效率,指针默认位于4字节边界上,即其地址必须是4的倍数。如果结构只包含一个字符和一个指针
1 2 3 4 | struct { char a; void* b; }; |
那么,
1 2 3 4 | 0 1 2 3 4 5 6 7 +---+- - - - - -+---------------+ | a | (unused) | b | +---+- - - - - -+---------------+ |
在您的例子中,额外的7个字节来自于3个字节(由于
1 2 3 4 5 6 7 8 | 0 1 2 3 4 5 6 7 8 9 a b c d e f +---------------+---+- - - - - -+---------------+- - - - - - - -+ | i |ch | | p | | +---------------+---+- - - - - -+---------------+- - - - - - - -+ 10 11 12 13 14 15 16 17 +-------------------------------+ | d | +-------------------------------+ |
... it gives me 24, and I am confused. What are the additional 7 bytes?
这些是编译器插入的填充字节。数据结构填充依赖于实现。
从维基百科,数据结构对齐:
Data alignment means putting the data at a memory offset equal to some multiple of the word size, which increases the system's performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding.
要稍微扩展一下Kennydm的优秀答案(Kenny-如果需要,请偷取这个来补充您的答案),这可能是编译器对齐所有变量后您的内存结构的样子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 0 1 2 3 4 5 6 7 +-------------------+----+-----------+ | i | ch | (unused) | +-------------------+----+-----------+ 8 9 10 11 12 13 14 15 +-------------------+----------------+ | p | (unused) | +-------------------+----------------+ 16 17 18 19 20 21 22 23 +------------------------------------+ | d | +------------------------------------+ |
因此,由于"ch"和"p"之间有3个字节的间隙,"p"和"d"之间有4个字节的间隙,所以您的结构得到了7个字节的填充,因此大小为24个字节。由于您的环境的
因为填充,所以是24字节。大多数编译器将数据填充到其大小的倍数。因此,一个4字节的int被填充为4字节的倍数。将8字节的双精度填充为8字节的倍数。对于您的结构,这意味着:
1 2 3 4 5 6 7 8 | struct struct_type{ int i; // offset 0 (0*4) char ch; // offset 4 (4*1) char padding1[3]; int *p; // offset 8 (2*4) char padding1[4]; double d; // offset 16 (2*8) }s; |
您可以这样优化结构:
1 2 3 4 5 6 | struct struct_type{ double d; int i; int *p; char ch; }s; |
sizeof(s)==17在大多数编译器上(20在某些其他编译器上)
$9.2/12状态-"在没有中间访问说明符的情况下声明的(非联合)类的非静态数据成员被分配,以便以后的成员在类对象中拥有更高的地址。未指定由访问说明符分隔的非静态数据成员的分配顺序(11.1)。实施协调要求可能会导致两个相邻的成员不被立即分配;也可能管理虚拟功能(10.3)和虚拟基类(10.1)的空间要求。"
因此,正如sizeof(double)和sizeof(int)一样,结构成员对齐的偏移量是未指定的,只是稍后声明的成员位于更高的地址。
有时还需要结构来维护所需的顺序。在这种情况下,如果您使用gcc,那么应该使用
更多信息,请参见此部分。
额外的大小来自数据对齐,即成员按4或8字节的倍数对齐。
编译器可能会将int和指针与4字节的倍数对齐,将double与8字节的倍数对齐。
如果将double移动到结构中的其他位置,则可以将结构的大小从24字节减少到20字节。但这取决于编译器。
参见comp.lang.c常见问题列表·问题2.12:
Why is my compiler leaving holes in structures, wasting space and preventing ``binary'' I/O to external data files? Can I turn this off, or otherwise control the alignment of structure fields?
允许编译器将结构的成员与地址对齐,以便更快地访问。例如,32位边界。标准只要求对象的成员按声明的顺序存储。所以当你需要一个精确的记忆位置时,一定要使用