字节对齐主要是为了提高内存的访问效率,比如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