c中的内存对齐

来源:互联网 发布:经济数据分析论文 编辑:程序博客网 时间:2024/05/20 02:54

1、结构体对齐原因有很大部分是因为计算机扫描的内存单元个数,也就是数据总线的大小。

    内存对齐的问题主要存在于理解struct等复合结构在内存中的存储结构。
在C语言中,结构是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如数组、结构、联合等)的数据单元。在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,但不一定是相邻存储,第一个成员的地址和整个结构的地址相同。

2、对齐的原则:

    原则1:数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储)。

    原则2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。(struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)

    原则3:收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。


    这三个原则具体怎样理解呢?我们看下面几个例子,通过实例来加深理解。

    例1:struct{
                 short a1;
                 short a2;
                 short a3;
                 }A;


         struct{
                 long a1;
                 short a2;
                 }B;

         sizeof(A) = 6; 这个很好理解,三个short都为2。

         sizeof(B) = 8; 这个比是不是比预想的大2个字节?long为4,short为2,整个为8,因为原则3。

    例2:struct A{
                 int a;
                 char b;
                 short c;
                 };


         struct B{
                 char b;
                 int a;
                 short c;
                 };

        sizeof(A) = 8; int为4,char为1,short为2,这里用到了原则1和原则3。

         sizeof(B) = 12; 是否超出预想范围?char为1,int为4,short为2,怎么会是12?还是原则1和原则3。

    深究一下,为什么是这样,我们可以看看内存里的布局情况。

                                  c
         A的内存布局:1111,     1*,      11

                                  c
         B的内存布局:1***,     1111,   11**

    其中星号*表示填充的字节。A中,b后面为何要补充一个字节?因为c为short,其起始位置要为2的倍数,就是原则1。c的后面没有补充,因为b和c正好占用4个字节,整个A占用空间为4的倍数,也就是最大成员int类型的倍数,所以不用补充。

    B中,b是char为1,b后面补充了3个字节,因为a是int为4,根据原则1,起始位置要为4的倍数,所以b后面要补充3个字节。c后面补充两个字节,根据原则3,整个B占用空间要为4的倍数,c后面不补充,整个B的空间为10,不符,所以要补充2个字节。

    再看一个结构中含有结构成员的例子:

    例3:struct A{
                 int a;
                 double b;
                 float c;
                 };

         struct B{
                 char e[2];
                 int f;
                 double g;
                 short h;
                 struct A i;
                 };

         sizeof(A) = 24; 这个比较好理解,int为4,double为8,float为4,总长为8的倍数,补齐,所以整个A为24。

         sizeof(B) = 48; 看看B的内存布局。

                                                                
         B的内存布局:11* *,1111, 11111111, 11 * * * * * *,1111* * * *, 11111111, 1111 * * * *

    省略宏与结构体中含位域字段两种情况说明,祥见原文。


3、考虑一个问题,为什么要设计内存对齐的处理方式呢?

      引入内存对齐的原因一方面在于硬件取指的方便,例如在32位总线系统上,如果一个int变量(4字节)放在一个4的倍数开始的内存地址中,则CPU可以一次将其数值读出,否则的话就要分两次才能读出。另一个重要的原因在于移植性的要求,也就是说不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。引入内存对齐的目的主要是为了可移植性以及最大限度提升硬件性能。详细可参看如下链接http://www.doc88.com/p-032414262099.html


4、 最后顺便提一点,在设计结构体的时候,一般会尊照一个习惯,就是把占用空间小的类型排在前面,占用空间大的类型排在后面,这样可以相对节约一些对齐空间。


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 华为荣耀6x忘记了密码怎么办 百度粉色衣服被洗变色了怎么办 粉色衣服放进洗衣机洗变色了怎么办 红米note5a应用锁忘了怎么办 索尼手机死机了怎么办不可拆卸电池 华为手机一直停留在开机画面怎么办 5s用11.4太卡了怎么办 华为荣耀5a手机声音小怎么办 牙签卡在手机插卡针里怎么办 捡的华为手机账号激活不了怎么办 华为平板激活手机密码忘了怎么办 捡个华为手机非要激活才能用怎么办 华为手机没激活想重新激活怎么办 华为手机激活总显示系统繁忙怎么办 华为荣耀7i进水了不开机怎么办 华为荣耀手机进水了怎么办开不开机 华为畅享5s变砖怎么办 我的苹果7机身内存满了怎么办 小米5x拆机后屏幕翘边怎么办 苹果手机设备禁止游戏登入怎么办 苹果7plus玩游戏掉频怎么办 孕期牙套子掉了基牙烂掉了怎么办 美团绑定的信用卡过期了怎么办 苹果6s手机开不开机怎么办 换了散热硅胶后还是死机怎么办 华为畅享6s掉啦怎么办 透明塑料壳被太阳晒的发黄怎么办 新买的手机壳有味道怎么办 刚买的手机壳有异味怎么办 bjd 光油把妆蹭掉了一点怎么办 软皮套手机壳如果大了怎么办 苹果手机自带相机拍照会晃屏怎么办 苹果x手机壳拆不下来怎么办 苹果手机5c屏幕没有反应怎么办 玩穿越火线屏幕两边是黑的怎么办? 8g内存只有2g可用怎么办? 三星7e微信分身打不开怎么办? 光猫的网口1不亮怎么办 两年前的发票发现名头有错误怎么办 苹果5s手机通话声音小怎么办 华为全网通手机电信卡打不了怎么办