C语言中结构体占用内存问题——字节对齐

普通数据类型比如int char float 我们很清楚知道它们占用几个内存,比如int占用4个字节,char占用一个字节等等,知道数据类型占用多少内存是很重要的,可以使我们的程序效率更高、运行速度更快、快速知道自己程序的bug…

这道题是自己秋招时面试嵌入式软件开发的一道笔试题,面试时也问了,当时自己回答的有些混乱,因此今天进行记录。

之前对结构体占用内存一直很混乱,到底是按照哪个变量类型计算内存?它是怎么计算?下面先看一个例子:

struct str1
    {
        char a;  //一个字节
        int b;   //4个字节
        float c;  //4个字节
        double d;  //8个字节
    };

str1这个结构体占用的内存是多少呢?如果用变量类型直接相加,得到的结果是17,但显然不是这样的。这个程序运行的**正确结果是24.**为什么呢?

因为为了CPU能够快速访问,提高访问效率,变量的起始地址应该具有某些特性,这就是所谓的“对齐”。比如4字节的int型变量,那它的起始地址就应该在4字节的边界上,即起始地址可以被4整除。

内存对齐的规则很简单:

    1.起始地址为该变量类型所占内存的整数倍,若不足则不足部分用数据填充至所占内存的整数倍。(暂时看不懂没关系,下面有图文解释)

    2.该结构体所占总内存为结构体成员变量中最大数据类型的整数倍。(首先需要介绍 有效对齐值:每个平台上的编译器都有默认对齐系数n,可以通过#pragma pack(n)来指定。有效对齐值就等与该对齐系数和结构体中最长的数据类型的长度两者最小的那一个值,比如对齐系数是8,而结构体中最长的是int,4个字节,那么有效对齐值为4。)

接下来我们分析上面的例子:

char型变量占一个字节,所以它的起始地址为0,而int类型占4个字节,它的起始地址应该是4(的整数倍),那么内存地址1、2、3就需要被填充。同样,float占用4个字节,而结构体中a,b两个成员变量占了0——7内存地址,c的地址从8开始,符合规则一,占用内存地址为8——11。double类型占8个字节,所以d的起始地址就应该从16开始,那么12、13、14、15内存地址就需要被填充。d从16地址开始,占用8个字节。整个结构体占用字节数为24,符合规则二。内存分配如图:红色区域为填充部分
在这里插入图片描述

下面再举一个例子,进一步说明:

struct str2
    {
        double a;
        int b;
        char c;
        double d;
    };

str2这个结构体占用的内存空间是多少呢?是24!怎么分析呢?

首先double类型的a占用内存地址为0—7,int类型的b起始地址为8,符合规则一,占用地址为8—11,char类型的c占一个字节,地址为12.那么double类型的d,起始地址为13吗?显然不是,满足规则一的地址是16,所以d起始地址为16,占用16----23。结构体总共24个字节,满足规则二。

如果这个结构体最后再加一个成员变量 char e,那这个结构体占用的内存是多少?char类型的e起始地址为24,占用地址为24,但是结构体一种有25个字节,就不满足规则二了,怎么办呢?为了满足规则二,我们将25—31进行填充,因此整个结构体占用32个字节。

参考文章:https://www.cnblogs.com/kl2blog/p/6908048.html

发布了94 篇原创文章 · 获赞 43 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/a932432866/article/details/98664297
今日推荐