数据的字节对齐(data structure alignment)

1.1.1 为什么需要字节对齐   

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

 

 

 

 

1.1.1   数据字节对齐讨论

我们在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

你可能感兴趣的:(c/c++内存管理)