一、为什么会存在内存对齐
假设内存的数据位宽是32bit,cpu发出的0,1,2,3地址在内存芯片看来都是0地址,因为内存芯片是32bit位宽的,即cpu发出的地址的低2bit内存芯片是看不到的。此时,如果我一个int型变量的地址在cpu内存空间的1地址上,cpu发出1地址,会造成两次内存读取命令,第一次从内存的0地址取4字节,第二次从内存的1地址读取4字节,拼凑出所需的int变量。两次访问造成浪费,若内存对齐则不会存在这个问题。
二、结构体的对齐原则
1、结构体成员变量对齐原则
a. 第一个成员变量的地址就是结构体的地址
b. #pragma pack(n)和成员变量长度之间的较小值作为此成员变量的对齐值。
2、结构体整体的对齐原则
结构体中长度最长的成员变量的长度和#pragma pack(n)之间的较小值作为整体的对齐值。
三、举例
1 #include <stdio.h> 2 3 typedef struct { 4 char a; 5 int b; 6 char c; 7 } type_t; 8 9 int main(void) 10 { 11 printf("%d\n", sizeof(type_t)); 12 }
此时结构体大小为12。
#include <stdio.h> #pragma pack(2) typedef struct { char a; int b; char c; } type_t; int main(void) { printf("%d\n", sizeof(type_t)); }
此时结构体大小为8。
四、关于默认#pragma pack(n)
不同编译器的#pragma pack(n)都有一个默认值,#pragma pack(n)的值也不是随意设置的,编译器可能支持某些特定的数。
可以将#pragma pack(n)理解为:对齐值的最低要求,如果本身比#pragma pack(n)还小,那么就按你自身的长度作为对齐值。
注:只是自己的理解,有错的话还请提醒我。谢谢!