C/C++内存对齐详解编程语言

前言

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

例:

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

输出:56

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

总结

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

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/20641.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论