有问题欢迎指正
关于内存对齐,是程序员指定将内存中数据放在“对齐”的位置上,这虽然造成了部分的内存空间的浪费,但可以提高计算机的速度。
这个“对齐”的位置,就是指可以被一个数整除的地址,这个数叫做“对齐参数”,一般是1,2,4,8,16……具体这个参数的选取就要用到#pragma pack( n )和__declspec( align(#) 中的n,#以及数据本身所占字节的大小,比如char=1,int=4(32位)……
编译器的缺省字节对齐方式(自然对界)
在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。
在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储(成员之间可能有插入的空字节),第一个成员的地址和整个结构的地址相同。
C编译器缺省的结构成员自然对界条件为“N字节对齐”,N即该成员数据类型的长度。如int型成员的自然对界条件为4字节对齐,而double类型的结构成员的自然对界条件为8字节对齐。若该成员的起始偏移不位于该成员的“默认自然对界条件”上,则在前一个节面后面添加适当个数的空字节。
C编译器缺省的结构整体的自然对界条件为:该结构所有成员中要求的最大自然对界条件。若结构体各成员长度之和不为“结构整体自然对界条件的整数倍,则在最后一个成员后填充空字节。
放一句公式:
当一个变量或结构体同时受两者影响时,__declspec( align(#) 的优先级高。
成员的地址决定于n及#,其要么是n的倍数,要么是#的倍数,要么是成员的大小的倍数,取最小。
结构体最后的大小于#有关,其要么是#的倍数,要么是结构体中最大对其参数的倍数,取最大。
C
#pragma pack( 4 )
__declspec( align(16)struct A
{
char a;数据成员对齐规则,第一个成员放在offset=0的位置,a放在[0]字节
short b; #=16>n=4>sizeof(short)=2,对齐参数选2,即b的地址必须可以被2整除,则[1]跳过,b放在[2,3]里
int c; #=16>n=4=sizeof(int)=4,对齐参数选4,c的首地址若不跳过为4,可以被4整除,则c放在[4,5,6,7]
};
则这个结构体最后的大小即sizeof(A)=8? 公式第二句,结构体A中最大对齐参数是int c的4,#=16>4,则取16的倍数,结构体最后的大小为16.
特殊:如果有结构体B中嵌套一个结构体A,如果A受__declspec( align(#) 影响过,由于优先级高,则A的对齐参数为#,如果没有影响过,A结构体中的最大对齐参数与n选最小值作为对其参数。
#pragma pack( 4 )
struct B
{
char a;同样,a放在[0]
A b; 结构体A受__declspec( align(#) 影响,对齐参数为16,长度为16,则b放在[16,17…… 32]
int c; c的对齐参数为4,放在[36,37,38,39]
};
现在的内存大小为40,能被4整除,所以sizeof(B)=40
如果不受__declspec( align(#) 影响
#pragma pack( 4 )
struct A
{
char a; a放在[0]字节
short b; b放在[2,3]里
int c; c放在[4,5,6,7]
};
现在A的内存大小为8,可以被4整除,所以sizeof(A)=8,A的最大对齐参数是4
#pragma pack( 4 )
struct B
{
char a;同样,a放在[0]
A b;比较A的最大对齐参数4和n=4的最小值,则b的对齐参数也是4,放在[4,5…… 11]
int c;对齐参数为4,放在[12,13,14,15]
};
现在的内存大小为16,能被4整除,所以sizeof(B)=16