zoukankan      html  css  js  c++  java
  • 数据对齐

    许多计算机系统对数据类型的合法地址做了一些限制,要求某种数据类型对象的地址必须是某个值K(2,4,8)的倍数,这种堆积限制简化形成了处理器和存储器系统之间接口的硬件设计,总之就是为了方便高效的读取数据,于是就有了数据对齐。

    struct S1
    
    {
    
       char k;
    
       double i;
    
       char c; 
    
    };

    Sizeof(S1)的值为24,而不是10,其原因就是数据对齐,如果是连续的存每个字段的值,那么double类型的i就可能分配在两个8字节的存储器块中,那么可能就要执行两次存储器访问,而现在的内存分配至这样的,k,i,c都占用8个字节,这样访问1次存储器就能得到double类型的i的值。k后面会有7个字节被浪费掉,也就是说i的偏移量是8,同样的c后面有7个字节被浪费掉,尽管它后面没有任何字段。这样显然太浪费内存了。如果我们将i和c的位置交换一下得到如下struct S2:

    struct S2
    
    {
    
       char k;
    
       char c;  
    
       double i;
    
    };

    现在Sizeof(S2)的值为16,而不是10也不是24。为了方便取出struct中最长的字段,即方便一次性读出,这个最长的字段前面和后面的字段所占的长度都必须是它的倍数,在这里就是double的长度8的倍数。而k所占的长度加c所占的长度为2,小于8,所以k和c的内存是连续的,c后面接着的是6个空白字节然后就是i所占的8个字节。我想你会有这样的疑问:为什么不直接把S1编译成S2?我只能说我也不知道,但有一个类似的情况就是:在类的初始化列表中,先定义的字段先初始化。那么在这里先定义的先分配内存, 还有就是struct根本没有产生多与的东西,来区分每个字段,要是编译器把他们的内存结果重组了,它又怎么知道自己读的是哪个字段呢。以上几句只是阿汉的个人理解,没有任何证明。

    有了上面的解释说明,在看一些简单的struct所需的内存就容易了。

    struct S3
    
    {
    
       char k;
    
       int c;
    
       double i;
    
    };

    Sizeof(S3):16,k与c连续,c后面3个字节空白,紧接着i占8个字节,共16个字节。

    struct S4
    
    {
    
       S3 a;
    
       int i[5];
    
    };

    那么sizeof(S4)的值为多少呢?40,a占16个字节,i占24个字节。a占16个字节我们是知道的,为什么int i[5]占24个字节,而不是20个字节呢,还是因为数据对齐,因为S3中的double i占8个字节,那么i占用的字节长度就一定是8的倍数,所以int i[5]占24个字节,而不是20个字节,如果S4中i的定义是int i[4],则i占16个字节,大家都没话说,没有疑问。

    同样的S4中的所有元素都是连续(会出现因为数据的长度不同而出现间隙空白),S4中的元素也会遵守数据对齐原则,其实我们可以把S4看成如下的样子:

    struct S4
    
    {
    
       char k;
    
       int c;
    
       double i;
    
    int i[5];
    
    };

    这样就好理解多了。

    如果S3和S4的样子如下

    struct S3
    
    {
    
       char k;
    
       int c;
    
       int i;
    
    };
    
     
    
    struct S4
    
    {
    
       S3 a[2];
    
       double i[5];
    
    };

    sizeof(S4)等于多少呢?

    作者:陈太汉

    博客:http://www.cnblogs.com/hlxs/

  • 相关阅读:
    Fix Installing .NET Framework 3.5 failed Error Code 0x800F0954 on Windows 10
    RHEL8安装五笔输入法
    Enable EPEL and Local Repository on RHEL8
    Why is Yum Replaced by DNF?
    检查Linux服务器是否被攻击的常用命令及方法
    IDEA 主题
    IDEA 如何显示一个类中所有的方法
    Appium 安装以及安装过程中遇到的问题
    Maven 如何发布 jar 包到 Nexus 私库
    java泛型的基本使用
  • 原文地址:https://www.cnblogs.com/hlxs/p/2711128.html
Copyright © 2011-2022 走看看