字节对齐主要是为了提高内存的访问效率,比如intel 32为cpu,每个总线周期都是从偶地址开始读取32位的内存数据,如果数据存放地址不是从偶数开始,则可能出现需要两个总线周期才能读取到想要的数据,因此需要在内存中存放数据时进行对齐。
内存对齐主要遵循下面三个原则:
结构体变量的起始地址能够被其最宽的成员大小整除
结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节
结构体总体大小能够被最宽的成员的大小整除,如不能则在后面补充字节
1、联合体同一时间只能存储1个被选择的变量,对其他成员变量赋值会覆盖原变量
2、联合体大小要至少能容纳最大的成员变量
3、联合体和结构体大小要是所有成员变量类型大小的整数倍
实例1
#include <iostream> typedef union UNI { char data1; unsigned short data2; double data3; char data4[30]; // 成员最大的占地址空间为30,但是需要满足double的8字节对齐,故需要补2个空位,为32字节大小。 int data5; }MYUNI; typedef struct STU { char data1; // 1 unsigned short data2; // (1 + 1) + 2,1字节不满足unsighed short对齐,补1个空位。 double data3; // ((1 + 1) + 2 + 4) + 8,(1 + 1) + 2 = 4字节不满足double对齐,补4个空位。 MYUNI uni; // ((1 + 1) + 2 + 4) + 8 + 32 char data4[3]; // 48 +3, 48字节满足字节对齐,直接加3。(如果后面已经没有数据了,则需要满足最终的8字节对齐,补5个空位。) int data5; // 51 + 4,最终需要满足double的8字节对齐,需要补空位1个成56. }MYSTU; int main() { std::cout << sizeof(double) << std::endl; std::cout << "MYUNI:" << sizeof(MYUNI) << " MYSTU:" <<sizeof(MYSTU) << std::endl; while(1); return 0; }
实例2:
typedef union u { char a; int b[5]; double c; int d[3]; }U; typedef struct s { int e; double f; short g; U h; char i[2]; }S;
U大小至少要容纳最大的b[5]=4*5=20字节,同时要是变量类型最大值得整数倍,即sizeof(double)=8的整数倍,所有sizeof(U)=24
s的大小计算需要看上一篇关于结构体大小的计算的文章sizeof计算结构体大小,联合体的自身对齐值为成员变量的最大对齐值,也就double的自身对齐值8,所以s得大小为4+4(对齐满足8的倍数)+8+2+6(对齐满足8的倍数)+24+2+6(对齐满足8的倍数)=56
实例3
typedef union UNI { int data; int data2[5]; double data3; }nu; // 24 typedef struct STU { int data; nu num; double data3; }stu1; std::cout << sizeof(stu1) << std::endl; // 4 + 4(对齐double8长度的补充) + 24(如果不是8的倍数则需要增加长度满足) + 8