1、处理器的差异
有的处理器,不容许在字节未对齐的地址上访问字或者是多个字的数据。比如sun sparc cpu,不容许在奇数字节上访问一个字,否则会出现异常。
2、出于CPU读取内存数据效率的考虑。
CPU访问内存的时候,都是以字为单位的,如果要读取的数据不在字节对齐的位置上,就要对一次读取数据的操作。比如,在下面的内存模式中,如果要读取0x0000C004处一个字的数据,那么只需要读取一次。如果要读取0x0000C009处一个字的数据,那么需要两次读取,0x0000C009~0x0000C00B一次,0x0000C00C一次。
Address |
Byte0 |
Byte1 |
Byte2 |
Byte3 |
0x0000C000 |
|
|
|
|
0x0000C004 |
01 |
02 |
03 |
04 |
0x0000C008 |
|
11 |
22 |
33 |
0x0000C00C |
44 |
|
|
|
0x0000C010 |
|
|
|
|
我们在32位x86机器上,以c语言的struct结构为例,讨论字节对齐问题。
C语言中,基本数据类型默认的对齐方式:
类型 |
长度(字节) |
对齐方式 |
Char |
1 |
1字节对齐 |
short |
2 |
2字节对齐 |
int |
4 |
4字节对齐 |
long |
4 |
4字节对齐 |
Float |
4 |
4字节对齐 |
double |
8 |
8字节对齐(windows);4字节对齐(linux) |
指针 |
4 |
4字节对齐 |
结构对齐的基本原则:
1、结构体对齐的字节数是此结构体所有成员对齐的字节数中的最大值。
2、结构体每一个成员自身要保持字节对齐。
3、如果结构体中包含嵌套子结构体,那么子结构体自身必须对齐。
4、对于整个结构体,要根据规则1中“结构体对齐的字节数”满足字节对齐,对于没有对齐的情况,需要在最后增加pading。
举例说明:
示例一:
//因为成员d1是double类型,8字节对齐,并且是所有成员中最大的,所以align_sub_test_1也是8字节对齐,根据原则1
struct align_sub_test_1
{
double d1;
char c1;
char pading[7];//为了保证此结构体字节对齐,所以需要填充7个空位,根据原则4
};
//因为成员sub0是8字节对齐,并且是所有成员中最大的,所以align_test_1也是8字节对齐,根据原则1
struct align_test_1
{
struct align_sub_test_1 sub0;
char c;
char array[2];
char pading[1];//为了保证成员i能够字节对齐,所以需要填充1个空位,根据原则2
short i;
char pading[2];//为了保证整个结构体8字节对齐,所以需要填充2个空位,根据原则4
};
测试如下:
size_t l = sizeof(struct align_test_1);//l的值是
struct align_test_1 a1;
a1.sub0.d1 = 1;
a1.sub0.c1 = 3;
a1.i = 7;
a1.c = 5;
a1在内存中的表示为:
00 00 00 00 00 00 f0 3f 03 cc cc cc cc cc cc cc 05 cc cc cc 07 00 cc cc
示例二:
//因为成员i是short类型,2字节对齐,并且是所有成员中最大的,所以align_sub_test_2也是2字节对齐,根据原则1
struct align_sub_test_2
{
short i;
char array[2];
char c;
char pading[1];//为了保证此结构体字节对齐,所以需要填充1个空位,根据原则4
};
//因为成员d1是double类型,8字节对齐,并且是所有成员中最大的,所以align_test_2也是8字节对齐,根据原则1
struct align_test_2
{
struct align_sub_test_2 sub1;
short s1;
short s2;
char pading[6];//为了保证成员d1能够8字节对齐,所以需要填充6个空位,根据原则2
double d1;
};
测试如下:
size_t l2 = sizeof(struct align_test_2);//l2的值是24
struct align_test_2 a2;
a2.sub1.i = 1;
a2.sub1.c = 3;
a2.s1 = 5;
a2.s2 = 7;
a2.d1 = 9;
a2在内存中的表示为:
01 00 cc cc 03 cc 05 00 07 00 cc cc cc cc cc cc 00 00 00 00 00 00 22 40
示例三:
//因为成员i是int类型,4字节对齐,并且是所有成员中最大的,所以align_sub_test_3也是4字节对齐,根据原则1
struct align_sub_test_3
{
int i;
char c;
char pading[3];//为了保证此结构体字节对齐,所以需要填充3个空位,根据原则4
};
//因为成员sub2是align_sub_test_3类型,8字节对齐,并且是所有成员中最大的,所以align_test_3也是8字节对齐,根据原则1
struct align_test_3
{
struct align_sub_test_3 sub2;
char c1;
char pading[1];//为了保证成员s1能够2字节对齐,所以需要填充1个空位,根据原则2
short s1;
char c2;
char pading[3];//为了保证此结构体8字节对齐,所以需要填充3个空位,根据原则4
};
测试如下:
size_t l3 = sizeof(struct align_test_3);//l3的值是16
struct align_test_3 a3;
a3.sub2.i = 1;
a3.sub2.c = 3;
a3.c1 = 5;
a3.s1 = 7;
a3.c2 = 9;
a3在内存中的表示为:
01 00 00 00 03 cc cc cc 05 cc 07 00 09 cc cc cc
参考:http://en.wikipedia.org/wiki/Data_structure_alignment