0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

对结构体的对齐理解上有点偏差

冬至配饺子 来源:最后一个bug 作者:bug菌 2022-08-10 18:08 次阅读

最近看到一些朋友在交流结构体对齐方面的一些问题,从他们的交谈中隐隐约感觉有几个朋友对结构体成员的对齐理解上有点偏差,不能说完全不对吧,毕竟这是老生常谈的问题了~

1、变量与内存

首先我们要明确,在嵌入式C语言中变量是什么?其实所谓的变量就是一小段内存。

当你随心所欲的在C程序中定义着各种变量,有没有想过他们是如何被安排到相应内存上的?

好吧,其实他们是怎么安排的,并不需要程序员太多的操心,这个映射过程都是编译器自动给大家分配的,(可以借助动态内存的角度去看待这个分配问题),因为大部分变量在一定内存区域上是可以任意选择地址的,比如你定义一个全局的int gVar 变量,在不进行特殊指定内存位置的情况下,其编译后所分配的内存地址并不一定每次都是相同的;当然,每次编译完成便会确定下来,并且程序中对该变量的访问,均会使用所确定下来的内存地址。

既然变量的地址分配过程由编译器自动完成,但有时候我们想把一些或者某个变量放在固定的内存地址处等,此时就需要通过一些语法来告诉编译器该如何分配这些指定变量内存的分配,比如要做复位数据恢复等。

然而内存的对齐问题也是对这些变量分配位置处理的一种方式,通常我们看到的align或者pack等就是来干预编译器的这块处理的。

2、结构体对齐

理解了上面的一个思路,那么我们来分析分析结构体对齐问题。

参考demo:

pYYBAGLzgjeAT8iJAAD1H7F0bjk340.pngpYYBAGLzgj2ARVKUAAC0Xb725aI681.png

运行结果:

poYBAGLzglmACdHRAAAwvobA02U713.png

以上编译结果采用的是32位编译器,默认对齐方式是4个字节,char类型占据1个字节,int占据4个字节,

下面简单分析一下结果:

1、默认方式,采用4个字节对齐,那么char后面需要填充3个字节,然后存放int类型,所以结构体大小输出为8。

2、1字节对齐方式,直接紧凑排列,很多人也叫不进行对齐处理,所以输出结果是5。

3、2字节对齐方式,其实和4个字节对齐是类似的,char按照2字节对齐,所以后面需要填充一个字节,这样int才能以两字节对齐排布,此时整个结构体占据6个字节。

4、4字节对齐方式与默认对齐方式一致,最后看看8字节对齐,此时char类型与int类型完全能够被8个字节容纳,而该结构体最大数据类型是4个字节,所以char后面会预留3个字节,进行4字节对齐,然后放置int类型,此时与4字节对齐是一致的。那么一些朋友会问,是不是在上面的8字节例子中再加入一个char类型的成员,整个结构体就会占据16个字节了呢?

pYYBAGLzgnOAR4kbAAA_oPyNI74889.png

其输出结果如下:

pYYBAGLzgpSARzfuAAAupVKITM0562.png

结构体所占据的字节是12个,那是不是认为8字节对齐没有意义呢?我们再看一个实验:

poYBAGLzgqeAFrKaAABIrxc_Zj4505.png

此时double占据了8个字节,按照前面的思路应该是4+8+4,应该最终结构体的大小是16个字节,而结果显示:

poYBAGLzgr6ABA9MAAAtrVniz38521.png

输出结果显示24=8+8+8的形式,大家也可以直接采用打印结构体成员地址的办法查看是几个字节对齐,有点晕,到底编译器这一块是怎么处理的呢?结论是:对齐字节数 = min<当前指定的pack值,最大成员所占字节大小>。

很多朋友其实研究到这个阶段基本上就没有再继续探究了~嵌入式C语言一定要跟硬件结合理解~

3、内存对齐

其实所谓的结构体对齐,并不是简单的1个字节、两个字节等多个字节的排列组合,而是在对应对齐地址上分布。首先对齐需要解决的问题是什么 ? 即为啥需要对齐?

提高内存的访问效率,也可以说是受CPU等硬件方面的限制,按照特定的对齐地址进行数据的访问要快于跨非对齐地址的内存访问;并且有些平台仅支持对齐方式访问,非对齐方式会直接运行错误。

poYBAGLzgteADWrAAABvtqExg18425.png

为了加快相关数据的正确访问,编译器会把相关的变量尽量的放到对齐的地址上,也就是默认的对齐方式,比如CPU在偶数地址上访问比较快,那么就会采用2个字节对齐的方式。
所以结构体内部成员并不是简单成员字节个数的对齐拼凑,而是让结构体成员落在对齐的地址上以便访问。如下图所示,当进行2字节对齐,如果只是简单的拼凑,两种分布都是可以的,但是左侧才是正确的2字节对齐方式,char成员变量的地址是2,int变量的地址是4,均为2字节的倍数。

pYYBAGLzgu6AXO9DAABqWWJvUDc646.png

总结一下: 结构体对齐不再是简单的字节个数的拼凑,而是要与内存地址进行挂钩~一般我们也可以理解为内存地址分配是多少字节的倍数,就是多少直接对齐~


审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    4979

    文章

    18256

    浏览量

    288009
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10417

    浏览量

    206477
  • C语言
    +关注

    关注

    180

    文章

    7523

    浏览量

    127589
  • 编译器
    +关注

    关注

    1

    文章

    1573

    浏览量

    48604
收藏 人收藏

    评论

    相关推荐

    使用LSM6DSOWTR里面的temperature sensor,为什么temperature offset达到了±15℃的偏差

    你好,我们想使用LSM6DSOWTR里面的temperature sensor,但是看到规格书里面对temperature sensor的描述,temperature offset达到了±15℃的偏差,这个地方有点无法理解,这个
    发表于 03-15 07:59

    keil arm工程中结构体1字节对齐如何实现

    在Keil Arm工程中,结构体的对齐方式可以通过使用特定的编译器指令或者关键字来实现。结构体的对齐方式会直接影响结构体变量在内存中的布局和
    的头像 发表于 01-05 14:40 1084次阅读

    ADE7858A测出来的有效值和实际值偏差有点大是什么原因导致的?

    尽管ADE7858A有校验,但校验前测出来的有效值和实际值偏差有点大,目前找不到原因,希望知道的专家能给予指导,谢谢各位! 具体数值如下: 输入的实际电压有效值为228v,但从VRMS寄存器里得到的数值换算后得到的值为217,相差11V,貌似
    发表于 12-26 06:03

    嵌套的结构体 字节是如何对齐

    嵌套的结构体,字节又是如何对齐的呢 先来看下面的代码 typedef struct stu1 { char ary [ 5 ] ; int a; }stu1; typedef struct stu2
    的头像 发表于 11-20 16:01 237次阅读
    嵌套的<b class='flag-5'>结构</b>体 字节是如何<b class='flag-5'>对齐</b>的

    什么是结构体的字节对齐现象

    什么是结构体的字节对齐现象 程序员,咱都用代码说话,先上 code: (说明:以下代码均在 ARM 平台上,使用 Keil 进行编译测试) # define offset_of (TYPE
    的头像 发表于 11-20 15:55 292次阅读
    什么是<b class='flag-5'>结构</b>体的字节<b class='flag-5'>对齐</b>现象

    求助,结构变量定义引用问题求解

    |= mask; } 如以上语句,GPIO_Type是个结构定义,定义了一个*base变量,在引用其中的成员时,是base->IMR的方式。这怎么理解; 如果是
    发表于 10-27 06:06

    为什么ST库函数结构没加对齐地址是连续的?

    为什么ST库函数结构没加对齐,地址是连续的
    发表于 10-15 08:11

    一个地址未对齐引起的HardFault异常

    一个地址未对齐引起的 HardFault 异常
    的头像 发表于 09-18 10:57 421次阅读
    一个地址未<b class='flag-5'>对齐</b>引起的HardFault异常

    keil MDK中程序读写结构成员进入HARDFAUL HANDLE RET为什么无法读写?

    大家好,请教一个问题,因需要我现在讲程序从IAR转入到keil之中,但是碰到一个奇怪的问题,是这样,我声明了一个结构,如下: #pragma pack(push) //保存对齐状态 #pragma
    发表于 08-25 07:58

    关于LSM6DSOWTR temperature sensor精度偏差的问题

    你好,我们想使用LSM6DSOWTR里面的temperature sensor,但是看到规格书里面对temperature sensor的描述,temperature offset达到了±15℃的偏差,这个地方有点无法理解,这个
    发表于 08-05 06:55

    关于G031 ADC结构设置的几个问题

    本人在使用ADC时想使用多通道模式,所以便在CUBEMX上将十九个通道全部打开(包括三个内部通道),生成代码以后详细看了一下结构的配置发现有几个疑惑, 1.ADC通道分为规则通道和注入通道,那么
    发表于 08-04 06:01

    C语言结构对齐介绍

    大家好,我是嵌入式老林,从事嵌入式软件开发多年,今天分享的内容是C语言结构对齐介绍,希望能对你有所帮助
    发表于 07-11 11:50 601次阅读
    C语言<b class='flag-5'>结构</b>体<b class='flag-5'>对齐</b>介绍

    IAR开发M453时出现定义结构错误的原因?

    在使用IAR开发M453时出现了一个问题,定义一个空结构就会报错,但是在结构中添加成员编译正常; 首先我想是不是对结构
    发表于 06-25 07:35

    RISC-V未对齐导致问题案例

    本文介绍未对齐导致问题案例
    的头像 发表于 06-08 10:04 1043次阅读
    RISC-V未<b class='flag-5'>对齐</b>导致问题案例

    为什么要结构对齐?为什么结构对齐那么重要?

    C语言结构对齐问题,是面试必备问题。我参与招聘技术面试的时候,也喜欢问这个技术点。
    的头像 发表于 05-26 14:10 659次阅读
    为什么要<b class='flag-5'>结构</b>体<b class='flag-5'>对齐</b>?为什么<b class='flag-5'>结构</b>体<b class='flag-5'>对齐</b>那么重要?