zoukankan      html  css  js  c++  java
  • C/C++内存对齐

    前言

    C语言中,结构体内存对齐问题算是比较常见的问题,虽然理解起来不难,但很多时候一不小心就会算错。比如给你一个 struct,让你 sizeof 计算一下需要占用多少字节,往往得到的结果比等于 struct 里面数据成员所占用的字节之和。

    例:

    #include <stdio.h>
    
    struct {
        int a;  // 4
        char b; // 1
    } test;
    
    
    int main(void) { 
        printf("%d
    ", sizeof(test));
        return 0;
    }

    输出:

    8

    分析:

    C语言中,int 占4个字节,char 占1个字节,理想情况下,这个结构体应该占用5个字节才对,为什么 sizeof 的结果却是8,这就不得不提到内存对齐了。

    内存对齐

    原则

    1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在 offset = 0 的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

    2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

    3、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。

    例1:

    #include <stdio.h>
    
    struct {
        int a;  // 4
        char b; // 1
    } test;
    
    
    int main(void) { 
        printf("%d
    ", sizeof(test));
        return 0;
    }
    
    输出:8
    分析:根据原则1、原则2,结构体中最大的成员是a,占用4字节,a存放在[0,3]中,b存放在[4],但由于原则2,需要对b进行补齐,b后面[5,7]需要填充,所以最终的结果是8

    例2:

    #include <stdio.h>
    
    struct {
        int a;   // 4
        char b;  // 1
        short c; // 2
    } test;
    
    
    int main(void) { 
        printf("%d
    ", sizeof(test));
        return 0;
    }

    输出:8

    分析:根据原则1和原则2,a存放在[0,3],b存放在[4],c存放在[6,7],b后面一个字节需要填充对齐

    例3:

    #include <stdio.h>
    
    struct {
        char a;  // 1
        int b;   // 4
        short c; // 2
    } test;
    
    
    int main(void) { 
        printf("%d
    ", sizeof(test));
        return 0;
    }

    输出:12

    分析:根据原则1和原则2,a存放在[0],b存放在[4,7],c存放在[8,9],a后面需要填充3个字节,c后面需要填充2个字节

    疑问:

    为什么例2和例3结构体内部成员都一致,只不过调整下顺序,内存占用却不一样?其实C语言在分配内存的时候,是根据结构体的成员属性定义从上往下进行分配的,有经验的程序员会在写结构体的时候对内存这块进行优化,从而提高代码的整体效率。

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

    例4:

    #include <stdio.h>
    
    struct {
        char b[2];  // 2
        int c;      // 4
        double d;   //8
        short e;    // 2
        struct {
            int f;    // 4
            double g; // 8
            short h;  // 2
        }a;
        int i;      //4
    } test;
    
    
    int main(void) { 
        printf("%d
    ", sizeof(test));
        return 0;
    }

    输出:56

    分析:结构体中含有结构体,则整体按最大数据成员 double 所占用8个字节的整数倍进行分配

    总结

    在计算机中,要么时间换空间,要么空间换时间,很明显,内存对齐就是空间换时间,按照一定的对齐规则,内存对齐的作用不仅是便于cpu快速访问,同时合理的利用内存对齐可以有效地节省存储空间。简而言之,内存对齐是为了高效的内存IO。

  • 相关阅读:
    Windows 和 Linux下使用socket下载网页页面内容(可设置接收/发送超时)的代码(用socket解释http,不错)
    HTTP协议 HttpWebRequest和 Socket的一点总结
    ASP.NET MVC基础学习
    利用HttpWebRequest和HttpWebResponse获取Cookie并实现模拟登录
    C#中Hashtable容器的了解与使用
    lib 和 dll 的区别、生成以及使用详解
    将SQL获取的信息传递到Email中
    关于ref与out的区别
    C#中指针使用总结
    一个打包文件导入器
  • 原文地址:https://www.cnblogs.com/lyc94620/p/14800754.html
Copyright © 2011-2022 走看看