内存对齐的两个基本原则:
一、结构体成员变量的地址偏移量(offset)是对齐参数的整数倍;
二、结构体各成员变量所占空间大小之和,是对齐参数的整数倍。
这里需要说明的是对齐参数有两种:变量对齐参数和编译器对齐参数
变量对齐参数如下表所示:
编译器类型 | char | short | int/float/指针 | double | |
Windows(32位)VC++ 6.0 | 长度 | 1 | 2 | 4 | 8 |
| 变量对齐参数 | 1 | 2 | 4 | 8 |
编译器类型 | char | short | int/float/指针 | double | |
Linux(32位)gcc | 长度 | 1 | 2 | 4 | 8 |
| 变量对齐参数 | 1 | 2 | 4 | 4 |
编译器对齐参数
该参数可以通过 #pragma pack(n)来设定,未设定的情况下选用默认值;
Windows(32位)VC++6.0 n的取值为1,2,4,8.默认值为8。
Linux(32位)gcc的取值为1,2,4.默认值为4。
实例分析:
对于原则一:这里的对齐参数是变量对齐参数和编译器对齐参数#pragma pack(n)中的较小者;比如假设结构体A中的变量int a的自身对齐参数是4,而编译器#pragma pack(n)的默认对齐参数为8,那么对齐参数是较小者4.
对于原则二:这里的对齐参数是所有变量的对齐参数中的最大值与编译器对齐参数比较,较小者作为原则二的对齐参数。
举个例子假如在结构体A中先后定义了两个变量int a;double b;对于变量a,它的自身对齐参数为4,而#pragma pack(n)值默认为8,则a的对齐参数为4;b的自身对齐参数为8,而#pragma pack(n)的默认值为8,则b的对齐参数为8。由于a的最终对齐参数为4,b的最终对齐参数为8,那么两者较大者是8,然后再拿8和#pragma pack(n)作比较,取较小者作为对齐参数,也就是8,即意味着结构体最终的大小必须能被8整除。
可以运行下面的实例进行练习(VS2008):
/*测试sizeof运算符 2016.03.08*/
//#pragma pack(4) //设置4字节对齐
//#pragma pack() //取消4字节对齐
typedef struct node1
{
int a;
char b;
short c;
}S1;
typedef struct node2
{
char a;
int b;
short c;
}S2;
typedef struct node3
{
int a;
short b;
static int c;
}S3;
typedef struct node4
{
bool a;
S1 s1;
short b;
}S4;
typedef struct node5
{
bool a;
S1 s1;
double b;
int c;
}S5;
int main(int argc, char *argv[])
{
printf("sizeof(char):%d,sizeof(short):%d,sizeof(int):%d,sizeof(float):%d,sizeof(double):%d\n",sizeof(char),sizeof(short),sizeof(int),sizeof(float),sizeof(double));
S1 s1;
S2 s2;
S3 s3;
S4 s4;
S5 s5;
printf("sizeof(s1):%d,sizeof(s2):%d,sizeof(s3):%d,sizeof(s4):%d,sizeof(s5):%d\n",sizeof(s1),sizeof(s2),sizeof(s3),sizeof(s4),sizeof(s5));
getchar();
return 0;
}
注: 对于结构体变量,它的自身对齐参数为它里面各个变量最终对齐参数的最大值。
参考:http://www.cnblogs.com/dolphin0520/archive/2011/09/17/2179466.html