内存对齐
一种提高内存访问速度的策略,cpu在访问未对其的内存需要经过两次内存访问,而经过内存对齐一次就可以了。
内存对齐系数
每个特定平台上的编译器都有自己的默认“对齐系数”(32位机一般为4,64位机一般为8),通常为4或8的倍数,
设置对齐参数: #pragma pack(n) ,n为对齐系数,不想对齐可以设置为1,设置为0,也表示为使用默认对齐
取消自定义字节对齐方式,使用默认对齐方式: #pragma pack()
sizeof
它的基本作用是判断数据类型或者表达式长度,要注意的是这不是一个函数,而是一个C++中的关键字!字节数的计算在程序编译时进行,而不是在程序执行的过程中才计算出来!
类型的长度与数据成员对齐
char //1
short //2
int //4
long // 64bit 8 32bit 4
double //8
*// 64bit 8 32bit 4
struct或union成员对齐规则如下:
对齐规则如下:
原则一:存放的首地址偏移量 % min(当前类型大小,对齐系数) == 0,假设对齐系数为8
char size = 1,min = (8,1) = 1,那么存放的首地址可以是任意地址 ,即首地址偏移量 %min == 0
short size = 2,min = (8,2) = 2,那么存放的首地址可以是0,2,4,6…… ,即首地址偏移量 %min == 0
int size = 4,min = (8,4) = 4,那么存放的首地址可以是0,4,8,12…… ,即首地址偏移量 %min == 0
double size= 8,min = (8,8) = 8,那么存放的首地址可以是0,8,16…… ,即首地址偏移量 %min == 0
long size= 8,min = (8,8) = 8,那么存放的首地址可以是0,8,16…… ,即首地址偏移量 %min == 0(64bit 8,32bit 4)
long long size= 8,min = (8,4) = 4,但是内存的存储按照4字节来,即即首地址偏移量 %min == 0
* size = 8,min = (8,8) = 8,那么存放的首地址可以是0,8,16…… ,即首地址偏移量 %8 == 0 (指针,oid,或有类型的int,long,char...,都是如此,32bit 4)
数组,size就是其对应类型的szie,比如char buffer[4],szie =1,min(8,1)= 1
原则二:结构体整体对齐,也称作二次对齐,结构体整体大小 % min(当前类型最大的大小,对齐系数) == 0
例子:
/****************** void * 和指定类型的指针 ***************/
1-1.默认64bit系统,即对齐系数为8,void类型指针
struct {
char a;
void *b;
char c;
} myStruct;
printf("sizeof %ld \n char %p\n void * %p char %p\n",sizeof(myStruct),&myStruct.a,&myStruct.d,&myStruct.c);
结果:sizeof 24
char 0x1006826b8 //1+7
void * 0x1006826c0 //前面需要补齐8的整数倍 8
char 0x1006826c8 //1
1+(7)+8+1 = 17,17%min(8,8) = 1,需要补齐7,17+7 = 24
1-2.默认64bit系统,即对齐系数为8,char类型指针
struct {
char a;
char *b;
char c;
} myStruct;
结果:sizeof 24
char 0x1006826b8 //1+7
char * 0x1006826c0 //前面需要补齐8的整数倍 8
char 0x1006826c8 //1
1+(7)+8+1 = 17,17%min(8,8) = 1,需要补齐7,17+7 = 24
1-3.默认64bit系统,即对齐系数为8,int类型指针
struct {
char a;
int *b;
char c;
} myStruct;
结果:sizeof 24
char 0x1006826b8 //1+7
int * 0x1006826c0 //前面需要补齐8的整数倍 8
char 0x1006826c8 //1
1+(7)+8+1 = 17,17%min(8,8) = 1,需要补齐7,17+7 = 24
/****************** 数组:大小为其类型的大小****************** /
2-1.默认64bit系统,即设置系数为8
#pragma pack(8)
struct {
char a;
int b[6];
char c;
} myStruct;
结果:sizeof 32
char 0x1006e66b8 //1 +3
int[] 0x1006e66bc // 4 *6 = 24
char 0x1006e66d4 //1
min = min(8,4) = 4;
1+(3)+24+1 = 29 ,29%4 = 1,需补3 29+3 = 32
2-2.默认64bit系统,即设置系数为8
#pragma pack(8)
struct {
char a;
char b[6];
char c;
} myStruct;
结果:sizeof 32
char 0x1006ba6b8 //1
char[] 0x1006ba6b9 // 1 *6 = 6
char 0x1006ba6bf //1
min = min(8,8) = 8;
1+6+1 = 8
/****************** 内存对齐系数设置****************** /
3-1.默认64bit系统,即设置系数为4
#pragma pack(4)
struct {
char a;
int b;
char c;
} myStruct;
结果:sizeof 12
char 0x1006926b8 //1 +3
int 0x1006926bc // 4
char 0x1006926c0 //1
min = min(4,4) = 4;
1+(3)+4+1 = 9 ,9%4 = 1,需补3 9+3 = 12
3-2.默认64bit系统,即设置系数为8
#pragma pack(8)
struct {
char a;
int b;
char c;
} myStruct;
结果:sizeof 12
char 0x1006926b8 //1 +3 min (1,8) = 1
int 0x1006926bc // 4 min (4,8) = 4
char 0x1006926c0 //1 min (1,8) = 1
min = min(8,4) = 4;
1+(3)+4+1 = 9 ,9%4 = 1,需补3 9+3 = 12
/****************** double 和long****************** /
4-1 long long
#pragma pack(8)
struct {
char a;
long long b;
char c;
} myStruct;
结果:sizeof 24
char 0x1006da6b8
long long 0x1006da6c0
char 0x1006da6c8
4-2 long
#pragma pack(8)
struct {
char a;
long b;
char c;
} myStruct;
结果:sizeof 24
char 0x10068e6b8
long 0x10068e6c0
char 0x10068e6c8
4-3
#pragma pack(8)
struct {
char a;
double b;
char c;
} myStruct;
结果:sizeof 24
char 0x10074a6b8
void * 0x10074a6c0
char 0x10074a6c8
网友评论