结构体、联合体的成员内存对齐的情况

作者: 良知犹存

作者:良知犹存

转载授权以及围观->欢迎添加WxId:Allen-Iverson-me-LYN

最近项目进行中,遇到一个小问题,在数据协议传输过程中,为了方便解析,就定义了一个结构体,在数据的指针传入函数的时候,用定义好的结构体进行强制转化,没想到一直解析失败,调试很久,终于反应过来,在用结构体指针对数据强制转换时,定义结构体没有注意到数据对齐,因为在底层实现中,传入的数据buffer是排列整齐的,而强制转化的结构体格式中,定义的时候没有使用attribute((packed))或者__packed强制数据对齐,导致结构体成员真实排列会按照成员中最大的变量的格式进行对其,缺少的地方被虚拟补充位置。

下面就稍微简单描述一下结构体数据对齐的讲解:

图片描述的两种实现结构对齐的声明,适用于结构体和联合的声明。


接下来展示几组声明结构体后成员变量对齐的方式:

/*第一个示例*/struct stc{    char one;    short two;    char three;    int four;} c,d;​​int main (void){    c.one=1;    return 0;}

第一个示例代码配合下方内存排列的图片,可以看到,在正常无特殊声明的情况下,结构体在内存排列是按照结构体成员中最大的变量的大小进行排列的。

第一处示例代码中,最大的成员变量是int型,一个int型在使用的32位ARM环境中占4个byte,所以在排列中,最小的排列单位是4byte,而其他类型,char占1个byte,short占2个byte,在排列的第一行的4个byte中,一个char+一个short类型为3byte,所以需要补上1byte的虚拟空间,第二行的4byte中,还剩下一个char和int,int单独占一行,所以char需要补上3byte才能排列整齐。

/*第二个示例*/struct __attribute__((packed)) stc{    char one;    short two;    char three;    int four;} c,d;​​int main (void){    c.one=1;    return 0;}

第二个示例代码配合下方内存排列的图片,可以看到,代码使用了attribute((packed))声明,这个声明的含义是,令相关的结构体与联合体强制一字节对齐。所以在内存中排列中,按照1byte的数据对齐方式,成员变量紧密排布。


/*第三个示例*/pragma pack (2)struct stc{    char one;    short two;    char three;    int four;} c,d;​​int main (void){    c.one=1;    return 0;}​

/*第四个示例*/pragma pack (4)struct stc{    char one;    short two;    char three;    int four;} c,d;​​int main (void){    c.one=1;    return 0;}

第三、四个示例代码配合下方内存排列的图片,可以看到,代码使用了pragma pack (n)声明,这个声明的含义是,令相关的结构体与联合体强制N字节对齐,这个声明和attribute((packed))功能类似,但是attribute((packed))只能进行一字节强制对齐,而pragma pack (n)对齐字节数,由n进行控制,所以有很多的灵活性。具体使用可以从下图成员对齐情况了解,此处就不进行赘述了。

———————— END————————

如果大家觉得有用,可以关注,有更多的文章。

原文作者:良知犹存

原文链接:https://www.cnblogs.com/conscience-remain/p/12580853.html

更多推荐

更多
  • 架构-Service Mesh 形态刍议 ” 们便开始锣鼓喧天地抬轿子迎进来。 基于这种认知愚人去年一年躲开了一些机会,但 "躲得了初一躲不过十五",今年刚进公司第一天,便被同事告知工作内容之一便是某系统的 Service Mesh 改造工作...... 考虑到饭碗,愚人还
    AI算法

  • 架构-sidecar 只能与同 Pod 内发? L,因为 MySQL 有些 bug,TiDB 将错就错照着实现了,而有些 bug 实在无法也去照着兼容实现,线上有社区同学质疑道,MySQL 也有 bug 吗? 且不论只要是软件都会有 bug,TiDB 为了兼容 MySQL,其 bu
    AI算法

  • 架构-微信架构 ...
    AI算法

  • 架构-流量控制中间件Sentinel笔记 本文主要分析阿里巴巴集团开源的流量控制中间件 Sentinel,其原生支持了 Java/Go/C++ 等多种语言,本文仅仅分析其 Go 语言实现。下文如无特殊说明,sentinel 指代 Sentinel-Go。1 基本概念 ...
    AI算法

  • 架构-RocksDB 笔记 进行调优。欲熟悉这些参数,必须对其背后的原理有所了解,本文主要整理一些 RocksDB 的 wiki 文档,以备自己参考之用。
    AI算法

  • 架构-信仰与存在 自身是一种信息体系,更是一个编排系统,编排其体系中的每个生物体。这个信息体产生于具有怀疑精神的、可对有效信息进行深度加工的人类先知,而后扩散,扩散范围俞广则力量俞强大。其生命力长久者则会成为宗教、民族意识以及国家认同,短暂则如流行文化,
    AI算法

  • 架构-人 - 机器 - 生命 rari即将出版新书《人类上帝:未来简史(Homo Deus: A Brief History of Tomorrow)》。在此书中,他提出新观点——未来计算机强大的算法,可能会让人类丢弃千百年来追求的自由意志,而把更多的事情交由机器决
    AI算法

  • 架构-一种基于Redis的多租户多粒度分布式内存文件系统 Redis采用了单进程架构,无法利用服务端多核的高性能,进而制约了其对服务器超大内存的使用能力。Redis能够使用的内存极限容量经验值为【8G, 24G】,超过这个容量上限其性能便急剧下降。 - 2 Scale out能力 基
    AI算法

  • 架构-分布式系统数据存储 为强一致(实时一致性)和弱一致(最终一致性),根据数据一致性要求的不同,读写流程也要做相应的改变。下面结合个人经验给出两种情况下的读写流程步骤。 一般的简单的分布式系统,缓存层可以使用redis集群,固化层则可以使用mysql或者mo
    AI算法

  • 架构-redis server 源码分析 redis启动流程: 1 加载配置;2 初始化redis master、slave以及sentinel的sri;3 注册事件事件serverCron。1.2.1 读取配置文件,...
    AI算法

  • 近期文章

    更多
    文章目录

      推荐作者

      更多