在第一篇博客已经对结构体内存对齐进行了一些简单的说明,在这篇则对其进行一些总结和补充说明:
总结:结构体内存对齐中存在默认对齐数(不同平台不一致),VS中为8,Linux中为4,也可以自己设定,在VS中运用#program pack(4),可将8改为4,最后可以用 #program pack()取消;
1:必须了解偏移值,如图:
数字0、1、2、3、4、5、6、7、8等是偏移值,大的偏移值-小的偏移值==之间内存空间个数,例如:8=8-0,4=4-0,4=8-4等;
2.对于结构体的第一个变量成员从0偏移值进行对齐(如为char类型1个字节,则占用0~1这1块空间,为int类型4个字节占用0~4这4块空间),由此对齐第一个;
3.对于第二个变量成员对齐到它自身与默认对齐数VS---8中较小者的整数倍的偏移值上去(如为int类型4个字节则从4偏移值进行对齐,double类型8个字节从8这个偏移值进行对齐);
4.对于第三个、第四个等剩下的成员变量对齐规律与第二个变量成员规律一致;
5.变量成员都对齐以后,结构体总大小==所有变量成员其中的最大对齐数的整数倍。
由此规律,分析这一段代码得出:
typedef struct S
{
char c1;
int i;
double d;
char c2;
}S;
int main()
{
printf("%d\n",sizeof(S));
return 0;
}
结果不为14,17,而为24(c1从0偏移值开始对齐,占0~1,1~4之间空间浪费,i则从4偏移值开始对齐,占4~8,d从8偏移值开始对齐,占8~16,c2从16偏移值开始,占16~17,此时总大小为17,不为变量成员double d(最大对齐数8的整数倍),所以结构体总大小==24,17~24之间空间浪费),如图:
补充说明:
1.对于结构体嵌套结构体,如这段代码:
typedef struct T
{
int i;
double d;
}T;
typedef struct S
{
char c1;
int i;
T j;
char c2;
}S;
int main()
{
printf("%d\n",sizeof(S));
return 0;
}
结果为:
其对齐规律与上整体相同,在一个结构体中遇到另一个结构体类型变量,则进入到另一结构体中对于其成员变量以相同规律进行对齐,最后结构体总大小==两个结构体中所有成员变量中最大对齐数的整数倍;
2.对于结构体中数组成员,如这段代码:
typedef struct S
{
char c[3];
int i;
}S;
int main()
{
printf("%d\n",sizeof(S));
return 0;
}
结果为:
上一段代码中,定义了char c[3],相当于定义了三个char类型成员,(若为int[4],相当于定义了四个int 类型的成员),然后其对齐规律与上总结一致。