简单讲解C语言中为什么要使用字节对齐

结构体填充与数据对齐

  • 结构变量的大小等于它包含所有变量的总大小。
  • 结构体填充:是编译器用来对齐内存偏移数据。
  • 字段填充:为了提高性能,编译器在结构体中利用 结构体填充 方法进行数据对齐。
  • 数据对齐:当CPU读写内存时,它都在小块内(字长或4个字节)进行。这种安排增加了系统的性能,有效地将数据存放在字长整数倍的偏移地址。
    • 结构体中每个数据类型都要对齐
    • 联合体中按照最大长度的数据类型对齐
    • 按照基本数据类型对齐

为什么要字节对齐?

现代计算机中内存的存储理论上都是按照 byte 大小来存储的,但实际上是按照 字长(word size) 为单位存储的。这样做是减少CPU访问内存的次数,加大CPU访问内存的吞吐量。比如同样读取8个字节的数据,一次读取4个字节那么只需要读取2次。
在这里插入图片描述

字节对齐方法

  • C编译器中采用#pragma指令#pragma pack(n) 编译器将按照 n 个字节对齐
  • _packed: 按照一字节对齐。packed一般会以降低运行性能为代价,由于大多数cpu处理数据在合适的字节边界数的情况下会更有效,packed的使用会破坏这种自然的边界数。
  • GCC编译器中采用 attribute((aligned (n)))方式对齐。

    让所作用的结构成员对齐在 n 字节自然边界上。如果结构体中有成员的长度大于 n,则按照最大成员的长度来对齐。

  • GCC编译器中采用attribute ((packed)) 取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
  • 结构体字节对齐的细节和具体编译器实现相关,但一般而言满足三个准则
    • 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
    • 结构体每个成员相对结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节 internal adding
    • 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节 trailing padding

为什么要用传递结构体指针变量?

结构体中数据成员变量的数据非常大,采用 结构体指针变量传递值 的效率要高,花费的时间少。

参考

猜你喜欢

转载自blog.csdn.net/breadheart/article/details/115445979