zoukankan      html  css  js  c++  java
  • 结构体中内存对齐

    1.结构体为什么要内存对齐(也叫字节对齐):

    其实我们都知道,结构体只是一些数据的集合,我们所说的结构体地址,其实就是结构体第一个元素的地址。这样,如果结构体各个元素之间不存在内存对齐问题,他们都挨着排放的。对于32位机,32位编译器(这是目前常见的环境,其他环境也会有内存对齐问题),就很可能操作一个问题,就是当你想要去访问结构体中的一个数据的时候,需要你操作两次数据总线,因为这个数据卡在中间,如图:

    结构体中内存对齐

    在上图中,对于第2个short数据进行访问的时候,在32位机器上就要操作两次数据总线。这样会非常影响数据读写的效率,所以就引入了内存对齐的

    2.内存对齐的规则:

    a.第一个成员起始于0偏移处

    b.每个成员按其类型大小和指定对齐参数n中较小的一个进行对齐

    c.结构体总长度必须为所有对齐参数的整数倍

    d.对于数组,可以拆开看做n个数组元素

    3.来几个小例子,画画图,有助于理解:

    第一个例子,代码如下:

    #include <stdio.h>
    struct _tag_str1
    {
      char a;
      int b;
      short c;
    }str1;
    struct _tag_str2
    {
      char a;
      short c;
      int b;
    }str2;
    int main()
    {
      printf("sizeof str1 %d",sizeof(str1));
      printf("sizeof str2 %d",sizeof(str2));
      return 0;
    }

    输出的结果分别是:str1为12 str2为8,分析的过程如下图:

    结构体中内存对齐

    看图很自然就知道了str1为12个字节,str2为8个字节。

    第二个例子,上面的那个例子有好多问题还没有考虑到,比如说上面的那个例子在8字节对齐,和4字节对齐的情况都是一样的。结构体中嵌套结构体的内存对齐怎么算,所以就有了这个例子,代码如下:

    #include <stdio.h>
    #pragma pack(8)
    //#pragma pack(4)
    struct S1
    {
        short a;
      long b;
    };
    struct S2
    {
        char c;
        struct S1 d;
        double e;
    };
    #pragma pack()
    int main()
    {
        struct S2 s2;
        printf("%d", sizeof(struct S1));
        printf("%d", sizeof(struct S2));
        printf("%d", (int)&(s2.d) - (int)&(s2.c));
        return 0;
    }

    我们分析下在4字节对齐的情况下输出的是,S2是20,S1是8,分析如图:

    结构体中内存对齐

    在4字节对齐的情况中,有一个问题值得注意:就是图中画1的地方。这里面本应short是可以上去的。但是对于结构体中的结构体一定要十分警惕,S1是一体的,short已经由于long进行了内存对齐,后面还空了两个字节的内存,其实此时的short已经变成了4个字节了!!!即结构体不可拆,不管是多少字节对齐,他们都是一体的。所有的圈都变成了叉。所以说结构体只能往前篡位置,不能改变整体。

    我们在分析一些8字节对齐的情况,如图:

    结构体中内存对齐

    同样,到这里又有一个字节对齐的原则要好好重申一下:就是以什么为对齐参数,首先我们要知道编译器或者自己定义的是多少字节对齐的,这个数为n。然后我们要看这个结构体中的各个数据类型,找到所占字节数最大的类型,为m。如果n大于m,就以m为对齐参数,比如说一个4字节对齐的结构体中都是short,那这个结构体以什么为对齐参数,当然是2了,如果m大于n,就以n为对齐参数,比如说在4字节对齐的情况下的double类型。

  • 相关阅读:
    Idea配置注释
    mysql省市区数据表
    php实现汉字转拼音的类
    git push时如果不再弹出用户和密码的输入提示框该怎么办
    .gitignore 忽略特殊文件无效
    vmware中CentOS7网络设置教程详解
    Tp5中配置多模块开发
    安装tp6 并使用多应用模式
    ldf和mdf文件怎么还原到sqlserver数据库
    git本地仓库与远程仓库建立连接。
  • 原文地址:https://www.cnblogs.com/jiangzhaowei/p/9129124.html
Copyright © 2011-2022 走看看