概述
字节对齐也称为字节填充,它是C++编译器的一种技术手段,主要目的是为了在空间和复杂度上达到平衡。简单而言,是为了在可接受空间浪费的前提下,尽可能对相同运算过程的最快(最少)处理。
基本对齐规则
在默认对齐边界条件下,字节对齐需要遵循以下三个原则:
数据成员对齐规则
结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始。结构体作为成员
如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储)。总体对齐
结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。
typedef struct bb
{
int id; //[0]....[3]
double weight; //[8].....[15]原则1
float height; //[16]..[19],总长要为8的整数倍,补齐[20]...[23]原则3
}BB;
typedef struct aa
{
char name[2]; //[0],[1]
int id; //[4]...[7]原则1
double score; //[8]....[15]
short grade; //[16],[17]
BB b; //[24]......[47]原则2
}AA;
int main()
{
AA a;
cout<<sizeof(a)<<" "<<sizeof(BB)<<endl;
return 0;
}
\\打印出的结果为48 24
自定义对齐边界
在默认情况下,编译器为每一个变量或数据单元按自然边界分配空间,同时还可以使用以下指令来修改默认边界条件:
- 使用伪指令#pragma pack(n),指定编译器按照n个字节对齐
- 使用伪指令#pragma pack(),取消自定义字节对齐方式。
例如,在上述代码前加上:#pragma pack(1)
,则打印的结果为32 16。#pragma pack(1)
告诉编译器,所有的对齐都按照1的整数倍对齐,即没有对齐规则。