• c语言结构体对齐的原因


    https://www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packing/
    https://stackoverflow.com/questions/3903164/why-misaligned-address-access-incur-2-or-more-accesses
    https://en.wikipedia.org/wiki/Data_structure_alignment

    • 实际上不仅仅是c语言,很多语言,或者说电脑程序,底层逻辑都是需要数据对齐,这是由电脑cpu,内存等基础架构决定的。

    • 系统32位或者64位,对应4或者8字节。以64位为例,cpu每次从内存读取数据是8字节(具体为什么是8字节,不太清楚)。

    • 为了增加效率,系统会按照8条线路从多个内存芯片(或者分区,类似的概念)分别读取1字节,这样是并行的,一次IO就可以解决。

    • 并且cpu读取数据,在偶数上读取速度更快,如果没有对齐,比如8个字节,从1地址开始,到8地址结束,则需要先读取0-7,再读取8-15,再把两次读取的数据拼接起来,中间增加了很多操作。如果数据保存在0-7位置上,只需要读取一次就行,并且获得数据的时候直接从0位置开始就好了,而不用计算偏移从1开始。

    • 结构体的大小为什么需要按照最大成员变量填充对齐呢?也是因为这个原因,cpu读取内存数据可以说是固定位置大小读取的,64位系统就是从内存的0-7开始,然后是8-15,16-23以此类推。如果结构体最后没有填充,按照最大变量类型对齐,就会导致连续的结构体数据(比如结构体数组)中的变量位置不再合理。比如int64,本来是0-7,8-15,两次读取就可以完成,如果因为前面没对齐,导致下一个结构体起始位置不对,int64有可能从2开始,那么就是2-7,8-15,16-17,需要三次才能取出来,还要拼接,并且像蝴蝶效应一样,会导致下面的数据出现更多这种问题。

    typedef struct structc_tag
    {
       char        c;
       double      d;
       int         s;
    } structc_t;
    

    按照参考网站给定的例子,c占用1个,填充7个,因为d要从其倍数开始,d占用8个,s占用4个,如果s后面不填充,那么结构体大小是20,如果定义structc_t structc_array[3];就会导致第二个数据是从20开始,d就会从28开始保存,导致读取数据出现上面说的,需要3次,还要拼接,所以结构体最后也要满足条件,就是最大变量的倍数,所以strctc_t是24,int后面需要填充4.

    • 除了结构体,实际上参数传递,局部变量等等,凡是需要读写内存的数据,理论上都会进行对齐操作,当然都是系统自己处理的,目的就是为了简化系统架构设计,增加效率,减少出错和干扰。如果有非对齐的数据会怎么样,这个要根据系统架构而定,支持的架构是没问题的,而不支持的架构就会报错。

    • 为什么不能对每个内存区域单独操作呢?现在我们知道,读取内存每次读取8字节(64位cpu),每次偏移是固定的一个参数,偏移0,就是0-7,偏移1,就是8-15,为什么不能为每一条通道增加一个偏移,单独计算,这样就可以随意读取,也不用对齐。这还是为了稳定性和简介性。如果增加8个,cpu设计复杂度会大大增加,各个通道间的信号干扰也会增加,导致cpu出错,计算也会增加,实际上性能可能并不理想,综合考虑,才变成了现在的设计。

    • 这样做会浪费内存吗?肯定会浪费内存,所以合理的安排结构体的顺序,尽量减少对齐

  • 相关阅读:
    将文件夹压缩为jar包——JAVA小工具
    android json解析及简单例子(转载)
    Eclipse RCP中获取Plugin/Bundle中文件资源的绝对路径(转载)
    右键菜单的过滤和启动(转载)
    eclipse rcp应用程序重启
    使用PrefUtil设置全局配置
    模拟器屏幕大小
    Android实现下载图片并保存到SD卡中
    PhoneGap与Jquery Mobile组合开发android应用的配置
    android WebView结合jQuery mobile之基础:整合篇
  • 原文地址:https://www.cnblogs.com/studywithallofyou/p/16693608.html
Copyright © 2020-2023  润新知