序
本节主要介绍结构体所占大小
结构体成员及之间的对齐规则
#include <iostream>
typedef struct person
{
int a;
char b[53];
struct person *p;
}person;
int main (int argc, char *argv[])
{
person b;
std::cout << sizeof(b) << std::endl;
}
结果为:4+53+7+8 = 72;
- 对齐要求确保了每个数据成员在内存中按其对齐需求存储
- 如果一个成员的对齐要求比前一个成员更高,编译器可能会在前一个成员和当前成员之间插入填充字节,以确保当前成员按照其对齐要求存储。
详解:
typedef struct person
{
int a;
char b[53];
struct person *p;
}person;
中的p对齐要求为8个字节,则需要将前面的总和4+53=57,填充到8的整数倍,即64.
当然对于结构体对齐要求还有一个
结构体总大小
先看测试:
- 测试 1:
$ g++ t.cpp -g -O0 -c
$ pahole -C person t.o
die__process_class: tag not supported 0x2f (template_type_parameter)!
struct person {
char b[53]; /* 0 53 */
char bb; /* 53 1 */
/* XXX 2 bytes hole, try to pack */
int a; /* 56 4 */
/* XXX 4 bytes hole, try to pack */
/* --- cacheline 1 boundary (64 bytes) --- */
struct person * pe; /* 64 8 */
/* size: 72, cachelines: 2, members: 4 */
/* sum members: 66, holes: 2, sum holes: 6 */
/* last cacheline: 8 bytes */
};
这段测试是算完结构体内部后刚好达到64。
2. 测试 2
$ g++ t.cpp -g -O0 -c
$ pahole -C person t.o
die__process_class: tag not supported 0x2f (template_type_parameter)!
struct person {
char b[53]; /* 0 53 */
char bb; /* 53 1 */
/* XXX 2 bytes hole, try to pack */
int a; /* 56 4 */
/* XXX 4 bytes hole, try to pack */
/* --- cacheline 1 boundary (64 bytes) --- */
struct person * pe; /* 64 8 */
char c; /* 72 1 */
/* size: 80, cachelines: 2, members: 5 */
/* sum members: 67, holes: 2, sum holes: 6 */
/* padding: 7 */
/* last cacheline: 16 bytes */
};
这段测试是算完内部为72+1=73, 想想看为什么报告中最后结果为80呢,答案在于:
结构体的总大小通常是其最大成员对齐要求的倍数。例如,如果结构体中最大的成员需要 4 字节对齐,那么整个结构体的大小通常也是 4 的倍数。
总结:
-
- 对齐要求确保了每个数据成员在内存中按其对齐需求存储。 //即int 4 bytes,char 1 byte,指针 8 bytes.
-
- 前面的数据类型可能会导致后面的数据类型需要填充字节以满足对齐要求。
-
- 结构体的总大小通常是其最大成员对齐要求的倍数