在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日