文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>c/c++结构体对齐小结...

c/c++结构体对齐小结...

时间:2010-08-06  来源:hexiankang1984

因为我看C++对象模型的时候,遇到了几个内存布局都是有关于对齐的一些细节,故此对结构体对齐再做一份小结,有人说:结构体对齐这个东西是依赖于编译器的,因此不用去研究,真的嘛?

也许是,也许不是,要看你是做那个行业的了,如果你是做系统地层,网络通讯,嵌入式系统的,一个字节的节省,也许对你是很大的期望呢。虽然具体的对齐方式是因编译器而异,但是对齐的基本原理是不变的,那个原理也许能指导我们编写程序的时候按照某个原则去进行。

不过,既然你用到了C或者C++,就多数是和系统底层有缘之人了,你说是嘛?呵呵。

现在先说在windows x86 32位机子下的MS vs2005编译器(就是:cl.exe for x86)下的对齐规则:

比如以下的结构体定义:

struct A

{

    int i;

    double d;

    char c;

};

问sizeof(struct A)在vs2005的大小?

现在说一下cl.exe(就是微软vs2005的编译器进程)在默认情况下是怎么做的:

1、对齐量的确定:找到A中最大的基本类型成员的大小,在本例中是8(double的大小).

2、当定义一个结构体变量struct A aA; 的时候,aA的起始地址要被由1确定的对齐量整除,在这个例子里,aA的起始地址一定要能被8整除)

2、然后开始分配int i,4字节的空间;再分配double d;注意double 是8字节,所以要分配在被8整除的地方,因此int  i后面空了4字节填充;

3、然后,分配char c;1字节,这个时候struct A的大小是4(这是int i;的) + 4 (这是填充的) + 8(这是double d;的) + 1 (这是char c;的)= 17;

4、最后,要求结构体总的大小要能被由1确定的对齐量整除,在这里是说struct A的大小要能被8整除,所以还要加上7字节的填充字符,一共是24字节。

从这里可以看出,vs2005的编译器的结构体填充有这样的规则(默认情况下,这个默认情况可以通过工程属性上面的选项修改):

1、对齐量的确定:结构体中最大的数据成员的字节数

2、当定义一个结构体变量的时候,起始地址一定能被确定的对齐量整除;

2、分配每一个成员的时候,该成员相对于起始地址的偏移(offset)要能被该成员的大小整除;

3、结构体总的大小能被确定的对齐量整除;

扩充的字节叫做pad(填充字节)

下面看linux g++ 3.4.3编译器在x86 的32位机子下的默认规则,那相对简单一些:(相当于VS2005中将对齐情况改成4字节对齐)

对齐的方式默认是4字节,所以每个成员都按照4字节方式对齐即可。上面的结构体的大小就是:

4 (int i;的大小) + 8(double 的大小) + 1(char 的大小) + 3 (为了4字节填充而补充的字节) = 16字节;

至于gcc的结构体变量的首地址分配的特征一时也找不到,还望各位多多指教。谢谢。

最后,如果定义一个没有任何成员的结构体,struct A{}; 该大小是多少呢?是1字节。如果定义了两个结构体变量struct A a1, a2; 1字节的填充能够使a1和a2的地址区分开来!

还有其他的编译器和操作系统就不是我所能知的了。

那么,这些规则也许不尽相同,但是给了我们一个编程时候的注意点,就是:

定义结构体的时候,成员最好能从大到小来定义,那样能相对的省空间。(至少不会比别的顺序差,一般情况下哈。)

比如以上的结构体,如果能这样定义:

struct A

{

    double d;

    int i;

    char c;

};

那么,无论是windows下的vs2005,还是linux下的gcc,都是16字节。

对齐情况还可以通过各个编译器给出的特性在代码中改,不过我没用过,就没有发言权,各位又需要可以参考别的文章。

以上的过程和推论是我看别的文章和上机试验的结果,如有不对之处,请各位指教,谢谢。

再说一点,对于有嵌套的情况,vs2005下的对齐我也不大确定,不过我的分析如下:

struct A

{

    char c;

    double d;

    int i;

};

struct B

{

    struct  A a;

    char c;

};

这种情况下,分析B的大小;

1、对齐量的确定:包括A中的各成员比较的,递归下去,比较各个基本类型成员的大小,去最大值,为8(double的大小);

2、起始地址和上面的一样,要求B的变量的其实地址能被8整除;

3、关于B中struct A a;的偏移和大小和将a单独作为结构体变量的时候一样(那样方便赋值运算)

剩下的和上面的规则相同;

所以:B的大小就是24(struct A)+ 1(char) +7(pad) = 32字节;

不知正确与否?还请诸位评判。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jiangnanyouzi/archive/2009/01/16/3793864.aspx

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载