class之位对齐

来源:互联网 发布:下载mp4是什么软件? 编辑:程序博客网 时间:2024/05/18 06:26

下面通过一个例子说明下位对齐及其位对齐的算法:

class A
{
int m;//4
char s;//1
double d;//8
int l;//4
};
void main()
{
 cout<<sizeof(A)<<endl;
 }

如果没有位对齐的话它输出的结果将会是4+1+8+4=17,可是事实是输出的24(32位机 vc6.0环境 当然和这个有关)其原因及其算法如下:

m占了4个字节所以是4,s占了1个字节而4是一的整数倍,所以为4+1=5,d占了8个字节,而5不是8的倍数所以要加上3变成8的倍数,所以就是5+3+8=16,l占了4个字节,16是4的倍数,所以为16+4=20。而因为总的大小要为class中最宽基本类型成员大小的整数倍,而这里最宽的是double既是8个字节,所以总的大小一定要为8的整数倍,而20不是8的整数倍,因此结果为:20+4=24.

其实位对齐的宽度是可以设置的,有两种设置方式如下:

1)在编译器里直接设置,即在vc6.0中直接设置,设置如下:

      project->settings->c/c++->Category(Code Generation)->Struct member alignment在这里可以设置。

2)可以用#pragma   pack(n)进行控制,方法如下:

     #include<iostream>
#include<string>
#pragma   pack(n)  // n为1,2,4,8,16

using namespace std;
class A
{
int m;//4
char s;//1
double d;//8
int l;//4
};
void main()
{
 cout<<sizeof(A)<<endl;
 } 

如果将n设置为1的话就是说对齐位的宽度为1,换句话说就是为1的整数倍,所以程序的运行结果就是:4+1+8+4=17

如果将n设置为2的话算法如下:

m为4是2的整数倍所以为4,s为1所以为4+1=5,可是5不是2的整数倍,所以是5+1+8=14,14+4=18,所以最后的结果是18.

其他的设置n的值是同理的。

 
为什么会有内存对齐?
    以下内容节选自《Intel Architecture 32 Manual》。
    字,双字,和四字在自然边界上不需要在内存中对齐。(对字,双字,和四字来说,自然边界分别是偶数地址,可以被4整除的地址,和可以被8整除的地址。)
    无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。
    一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。
    某些操作双四字的指令需要内存操作数在自然边界上对齐。如果操作数没有对齐,这些指令将会产生一个通用保护异常(#GP)。双四字的自然边界是能够被16整除的地址。其他的操作双四字的指令允许未对齐的访问(不会产生通用保护异常),然而,需要额外的内存总线周期来访问内存中未对齐的数据。

简单一点说为什么会有位对齐,就是从cpu对内存的访问周期上考虑的,这样虽然是浪费了一点空间,可是加快了cpu的处理速度。

  以上是本人的见解,如有不对之处,希望大家多多指正。

原创粉丝点击