在C/C++编程中,有一个align的问题经常被忽略。所谓align的问题,就是指通过对原始数据类型按边界对齐,CPU可以达到更好的访问效率。align的基本原则是,数据类型以本身的size作为边界对齐。比如,char按1byte对齐,short按2byte对齐,int按4byte对齐等等。
在定义structure,union,class的时候,需要考虑到这个align的问题。如果访问了Unaligned的数据,不同的CPU和不同的OS会有不同的处理,在多平台开发中尤其要注意这个问题。
x86对Unaligned的数据的访问进行了处理,然而对性能有影响。一些RISC类型的CPU在对Unaligned的数据进行访问的时候,会发生非正常中断的现象,一些RISC类型的CPU会发出一个异常给OS,由OS决定是否处理。
概括来说,对Unaligned的数据的访问,有下面四种情况: 1,CPU以性能为代价,对Unaligned的数据的访问进行处理。 2,CPU抛出异常给OS,OS对Unaligned的数据的访问进行处理。 3,CPU抛出异常没有被OS处理,这样会产生非正常中断等严重的问题产生。 4,编译器对Unaligned的数据的访问进行处理,同样必须以性能为代价。
对于编译器对Unaligned的数据进行处理,为了达到align的目的,自动加入了pading的数据。这时候需要注意这些pading的数据,尤其是使用指针的时候,通常会得到一些预料之外的结果。
下面是一个在VC++下的例子:
============================================================= #include "stdafx.h" #include <stdio.h>
#pragma pack(1)
struct s1 { char i; short j; int k; };
struct s2 { char i; struct s1 j; };
#pragma pack()
/************************** struct s3 { char i; char _pad[1]; short j; int k; }; **************************/ struct s3 { char i; short j; int k; };
/************************** struct s4 { char i; char _pad[3]; struct s3 j; }; **************************/ struct s4 { char i; struct s3 j; };
/************************** struct s5 { char i; char _pad1[3]; int k; short j; char _pad2[2]; }; **************************/ struct s5 { char i; int k; short j; };
struct s1 t1; struct s2 t2; struct s3 t3; struct s4 t4; struct s5 t5;
int main(int argc, char* argv[]) { int i; char *pi; short *pj; int *pk;
// 7 /*************************** struct s1 { char i; short j; int k; }; ***************************/ i = sizeof(t1); printf("%d\n", i);
// 8 /************************** struct s2 { char i; struct s1 j; }; **************************/ i = sizeof(t2); printf("%d\n", i);
// 8 /************************** struct s3 { char i; char _pad[1]; short j; int k; }; **************************/ i = sizeof(t3); printf("%d\n", i);
// 12 /************************** struct s4 { char i; char _pad[3]; struct s3 j; }; **************************/ i = sizeof(t4); printf("%d\n", i);
// 12 /************************** struct s5 { char i; char _pad1[3]; int k; short j; char _pad2[2]; }; **************************/ i = sizeof(t5); printf("%d\n", i);
t1.i = 1; t1.j = 2; t1.k = 3;
// 1, 2, 3 pi = &t1.i; pj = (short* )(pi + 1); pk = (int* )(pi + 3); printf("%d, %d, %d\n", *pi, *pj, *pk);
t3.i = 1; t3.j = 2; t3.k = 3;
// 1, 512, 768 pi = &t3.i; pj = (short* )(pi + 1); pk = (int* )(pi + 3); printf("%d, %d, %d\n", *pi, *pj, *pk);
return 0; }
/************ OUTPUT ************ 7 8 8 12 12 1, 2, 3 1, 512, 768 ******************************/ =============================================================
参考资料: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_PREDIR_pack.asp Bret S. Pehrson : Unaligned Data Access
Jady Leung 2004年9月25日

|