对齐指的是如何安排对象在内存中地址,要求某种类型对象的地址必须是某个值K(通常是2,4,8)的倍数,假设处理器总是从内存中取8个字节,则地址必须为8的倍数。
对齐的原则是任何K字节的基本对象的地址必须是K的倍数。
_Algnof 运算给出一个类型的对齐要求,
size_t d_align = _Alignof(float);
可以使用_Alignas说明符指定一个变量或类型的对齐值。但是,不应该要求该值小于基本对齐值。
_Alignof(double) char c1;
_Alignof(8) int i;
结构体对齐
结构体是多类型对象,确保每种数据类型都是按照指定方式来组织和分配,即每种类型都满足它的对齐规则。
考虑如下结构体。
struct s1 { int i; char c; int j; };
假设编译器用最小9字节分配。如下
0 4 5 9
[ i ] [ c ][ j ]
不满足字段i和字段j的4字节对齐要求。需要进行填充。如下
0 4 5 8 12
[ i ] [ c ][ 填充3字节 ][ j ]
结果,j的便宜了为8,整个结构体大小为12个字节。假设其实地址为(第一个i需要4倍数的地址)4x,c地址是4x+1,j地址就是 4x+8
结构体往后填充
考虑结构体
struct s1 { int i; char c; int j; char k; };
填充后如下。
0 4 5 8 12 13
[ i ][ c ][ 填充3字节 ][ j ][ k ]
考虑结构体数组的内存分布,即struct s1 a[2];
0 4 5 8 12 13 17
[ i ][ c ][ 填充3字节 ][ j ][ k ][ i ][ c ][ 填充3字节 ][ j ] [ k ]
在第二个i位置,它的地址为13+初始地址。初始地址一定为4x(能被4整除),13+4x不能被4整出,进行后填充。
0 4 5 8 12 13 16 20 21 24 28
[ i ][ c ][ 填充3字节 ][ j ][ k ][填充3字节][ i ][ c ][ 填充3字节 ][ j ][ k ]
所以,为了浪费最小,结构体字段排序最好按照字节类型小的开始。比如上面的结构体
struct s1 { char k; char c; int i; int j; };
0 1 2 4 8 12
[ k ][ c ][ 填充2字节 ][ i ][ j ]
也不需要后填充。