前言
俗话说的好,磨刀不误砍柴工,对于C结构体的相关知识还是要先了解清楚,当然如果已经了然于胸,此处可忽略
咱就直奔主题,看例子急速掌握。小白的我还是要先从基本的开始(Ps:白了很多次,还是白,没办法,太笨了)
基础一:为啥要内存对齐?
对于这个问题,之前小白没有太深的理解,后来大神的代码看多了,项目遇到坑以后(果然疼了才能记得住)才
幡然醒悟,要好好学习。通用说法:就是为了提高代码效率,利于平台移植,空间换时间;对于小白而言,最主要
的是节约空间,提高空间利用率,毕竟小白的设备内存很金贵。
基础二:内存对齐三原则(没有#pragma pack宏定义下)
1)、首地址0为结构体内第一个元素位置
2)、每个结构体内元素的首地址是自身基本数据类型大小的整数倍
3)、结构体的总大小,是其所有元素所含最大类型数的整数倍
基础三:内存对齐三步走
第一步:确认最大对齐数,三种情况取其中较小值
1)、预编译设置#pragma pack(8),取值只能是 0,1,2,4,8,16
2)、结构体中最大成员基本数据类型,比如:char,int,double 最大是8
3)、设备默认值 WIN vs qt 默认8字节对齐,Linux 32位 默认4字节对齐,64位默认8字节对齐
最大对齐数可以理解为:每次分配空间给数据时的最大值
第二步:给每个数据分配空间,从0地址开始,每次分配给数据的空间起始地址(相对于0地址)都必须是数据基本
类型大小与最大对齐数中较小值的整数倍
第三步:结构体的总大小必须是最大对齐数的整数倍
注意点:
1)、对于嵌套的结构体,其空间起始地址必须是嵌套结构体的最大对齐数
2)、对于联合体,他们共用一个空间
废话不多说,直接上例子
/*
结构体A
第一步:预编译设置为8 ,成员最大基本数据类型为:double 8,(设备Linux 32位)默认 4,故最最对齐数取 4
第二步:依次按数据分配
1)char 1< 4 取对齐数 1 起始地址 0 是1的整数倍 0+1=1
2)int 4= 4 取对齐数 4 当前地址是1 不是4的整数倍,故补齐,分配地址从4开始 4+4=8;
3)double 8>4 取对齐数 4 当前地址是8 是4的整数倍, 8+8=16;
4)short 2<4 取对齐数 2 当前地址是16 是2的整数倍, 16+2=18;
第三步:当前结构体总大小为18,不是最大对齐数4的整数倍,故补齐,结构体总大小为:20
*/
#pragma pack(8)
typedef struct _A
{
char a;
int b;
double c;
short e;
//float d;
}A;
#pragma pack()
/*
共用体B
取共用最大空间值 int 4
*/
#pragma pack(8)
typedef union _B
{
char f:1;
int g:8;
int h;
}B;
#pragma pack()
/*
结构体C
第一步:预编译设置为8 ,成员最大基本数据类型为:double 8,(设备Linux 32位)默认 4,故最大对齐数取 4
第二步:依次按数据分配
1)char 1< 4 取对齐数 1 起始地址 0 是1的整数倍 0+1=1
2)结构体A 最大对齐数为 4=4 当前地址是1 不是4的整数倍,故补齐,分配地址从4开始;
结构体内依次为:4+1=5;(与结构体A取法一致)
8+4=12;
12+8=20;
20+2=22;
不足补齐 24
3)char 1<4 取对齐数 1 当前地址是24 是1的整数倍, 24+2=26;
4)共用体B 最大数据长度为4,对齐数为4 ,当前地址是26 不是4的整数倍,故补齐28+4=32;
5)short 2<4 取对齐数 2 当前地址是32 是2的整数倍, 32+2=34;
第三步:当前结构体大小为34,不是最大对齐数4的整数倍,故补齐,结构体大小为:36
*/
#pragma pack(8)
typedef struct _C
{
char C_a;
A C_b;
char C_e[2];
B C_c;
short C_d;
}C;
#pragma pack()
int main(int argc, char const *argv[])
{
printf("sizeof (double) =%d\n",sizeof(double));
printf("sizeof (float) =%d\n",sizeof(float));
printf("sizeof (short) =%d\n",sizeof(short));
printf("sizeof (A) 20 =%d\n",sizeof(A));
printf("sizeof (B) 4 =%d\n",sizeof(B));
printf("sizeof (C) 36 =%d\n",sizeof(C));
return 0;
}
结果:
sizeof (double) =8
sizeof (float) =4
sizeof (short) =2
sizeof (A) 20 =20
sizeof (B) 4 =4
sizeof (C) 36 =36