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

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


审核编辑:刘清

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

    关注

    5087

    文章

    19158

    浏览量

    306445
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10890

    浏览量

    212405
  • C语言
    +关注

    关注

    180

    文章

    7614

    浏览量

    137250
  • 编译器
    +关注

    关注

    1

    文章

    1639

    浏览量

    49198
收藏 人收藏

    评论

    相关推荐

    ADR4520的负载调整度有点偏差是什么原因引起的?

    的负载调整度有点偏差(应该是等效内阻大吧),所以准备用ADS1255资料推荐的OPA350做一级缓冲,不过发现有以下几个问题让我感觉到很困惑: 1.OPA350的失调电压居然高达1mV(这个数值可以
    发表于 12-18 06:56

    KiCad的对齐工具不好用?

    “  不存在的。唯一的原因是您还没有学会怎么用。   ” 对齐命令在哪里? KiCad的对齐命令(Align)藏得比较隐蔽,既不在菜单栏,也不在工具栏。右键的菜单中默认也不存在。只有当您 选中两个或
    的头像 发表于 12-04 18:15 210次阅读
    KiCad的<b class='flag-5'>对齐</b>工具不好用?

    结构成员的顺序会影响结构的大小吗

    相同的结构成员,如果把顺序调整一下,会不会影响结构的大小? 答案是会的,这主要跟字节对齐有关。 比如这样的
    的头像 发表于 11-25 16:24 237次阅读

    ARM嵌入式系统中内存对齐的重要性

    做嵌入式系统软件开发,经常在代码中看到各种各样的对齐,很多时候我们都是知其然不知其所以然,知道要做好各种对齐,但是不明白为什么要对齐,不对齐会有哪些后果,这篇文章大概总结了内存
    的头像 发表于 11-11 17:17 960次阅读
    ARM嵌入式系统中内存<b class='flag-5'>对齐</b>的重要性

    C语言和C++中结构的区别

    同样是结构,看看在C语言和C++中有什么区别?
    的头像 发表于 10-30 15:11 307次阅读

    TLV9062IDR的电流采样电路,请问运放本身偏差大小是否正常?

    大家好,下图是TLV9062IDR的电流采样电路。 实际测试时发现运放本身的偏差有点大,同一块板子用1号运放时,软件在电流为30A时读取的值偏小0.35A。换上2号运放时,读值反而会偏大0.2A
    发表于 08-15 08:17

    ota升级的库中,结构upgrade_server_info中pespconn的作用是什么?

    check_cb; struct espconn *pespconn; }; 这个结构中已经有ip,port,pespconn这个结构
    发表于 07-12 06:33

    聚徽触控-工控一机和 PLC 一机有什么不同

    在工业自动化领域,工控一机和 PLC 一机都扮演着重要角色。尽管它们在某种程度上有所重叠,但它们在功能、应用和设计结构等方面存在显著的不同。工控一
    的头像 发表于 06-21 10:05 525次阅读

    你是否真的了解结构占用了多少字节?

    结构成员所占内存空间大小一般情况下,如果想知道结构成员的内存占用情况需要:1、先用结构在内
    的头像 发表于 06-04 08:04 536次阅读
    你是否真的了解<b class='flag-5'>结构</b><b class='flag-5'>体</b>占用了多少字节?

    嵌入式中C语言结构基本实现

    C语言中的数组只能允许程序员定义存储相同类型数据。但是结构是C语言编程中允许您存储不同数据类型的数据。 结构的定义     要想定义结构,必须用到 struct 关键字,struct
    的头像 发表于 05-11 08:49 1097次阅读
    嵌入式中C语言<b class='flag-5'>结构</b><b class='flag-5'>体</b>基本实现

    深入理解 FPGA 的基础结构

    转载地址:https://zhuanlan.zhihu.com/p/506828648 文章很详细的介绍了FPGA的基础结构,能更直观的理解内部结构原理。对深入学习很有帮助。 以下是正文: 这一段
    发表于 04-03 17:39

    C语言结构史上最详细的讲解【软件干货】

    struct结构数据类型 前言 我们知道,在C语言中有一些基本的数据类型,如 char int float long double string(c99) 等等数据类型,他们可以表示一些事物
    的头像 发表于 03-28 17:52 810次阅读

    STM32关于FLASH的编程对齐错误标志位(PGAERR)的疑问求解

    大神们,我现在正在做一个应用,需要熟悉STM32F4的FLASH的任何错误标识,以用于特殊情况下的错误标识判断做相应处理,但是针对FLASH的编程对齐错误标志(PGAERR)与我理解不同。 原文
    发表于 03-22 07:59

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

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

    求助,关于G031ADC结构设置的几个疑问求解

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