我的C语言.结构体以及内存对齐

我的C语言.结构体以及内存对齐,第1张

结构体内存对齐
为什么要有内存对齐
  • 首先我们要明白CPU不是我们想象中,想怎么样读取内存就可以怎么样读取内存的。


  • 对于CPU来说,有可能一次读取2个字节,4个字节或8个字节,而且都是相当于0地址处来读取的。


  • 举一个易懂的例子,假设一个double的数据从0地址开始存储,那么他的存储位置为0 1 2 3 4 5 6 7 。


    如果CPU一次读取4个字节,那么从0地址处开始依次读4个字节,只需读取两步就可以。


    如果double的数据从1地址开始存储,那么他的存储位置为1 2 3 4 5 6 7 8,则CPU需要先读取0 1 2 3,4 5 6 7,8 9 10 11。


    读取三步才能读取到这个double的数据。


  • 如果采用内存对齐,这个double的数据只会从0,4,8,12……这样的位置开始存储。


    CPU可以从0,4,8,12……这样的位置直接开始读,因为CPU相当于0地址处一次读取4的字节刚好吻合。


  • 所以结构体的内存对齐是拿空间来换取时间的做法。


    当然还有其他的原因,比如平台原因,性能原因。



内存对齐规则
  1. 不管怎么声明结构体,第一个成员在与结构体变量偏移量为0的地址处开始存放。


  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的偏移量处。


  3. 对齐数=编译器默认的一个对齐数与该成员空间大小的较小值。


  4. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。


  5. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。


最后,在设计结构体的时候,既要满足对齐,又要节省空间的方法是:让占用空间小的成员尽量集中在一起。



#pragma pack的使用与offsetof的模拟
1.
  • #pragma pack(N)是用来修改编译器的默认对齐数。


  • #pragma pack( )取消设置的默认对齐数,还原为默认。


 2.
  • offsetof是用来计算结构体中某变量相对于首地址的偏移量。


  • offsetof不是函数,而是一个#define定义的宏。


  • offsetof(结构体名字,结构体成员名)返回的类型是size_t。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/634969.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-04-16
下一篇2022-04-16

发表评论

登录后才能评论

评论列表(0条)

    保存