C/C++中align的问题

类别:编程语言 点击:0 评论:0 推荐:

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

本文地址:http://com.8s8s.com/it/it27139.htm