C语言结构体的内存对齐

本是古典 何须时尚 2022-07-11 14:57 262阅读 0赞

什么是结构体?

学过C语言的大家应该都学到过结构体,结构体是一种聚合数据类型,它可以把不同类型的数据存储在一起,我们把结构体中存储的数据叫做结构体成员。

结构体的内存对齐

了解了结构体后,我们来谈一谈结构体在计算机系统中是如何存储的,首先,我们来看看下面这段代码:

  1. struct A
  2. {
  3. char a;
  4. int b;
  5. char c;
  6. };
  7. int main()
  8. {
  9. struct A a;
  10. printf("Size(A::a):%d\n", sizeof a.a);
  11. printf("Size(A::b):%d\n", sizeof a.b);
  12. printf("Size(A::c):%d\n", sizeof a.c);
  13. printf("Size(A):%d\n", sizeof a );
  14. return 0;
  15. }

这段代码中我们分别定义了三个结构体成员,按顺序分别是char类型,int类型和char类型。在main函数中我们定义了结构体变量a,并分别用printf打印了各个结构体成员的大小和结构体的大小,结果如下:
这里写图片描述
看到结果后我们思考一个问题?为什么三个结构体成员的大小加起来不等于结构体的总大小呢,要弄明白这个问题,就需要我们理解计算机中是如何存储结构体的了。

内存对齐的相关规则

原则一:结构体中元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每一个元素放置到内存中时,它都会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始(以结构体变量首地址为0计算)。
现在我们通过原则一来看一看上面代码中所定义的结构体中的成员是如何在计算机系统中存储的。
这里写图片描述

关于结构体成员的偏移量我们可以通过offsetof宏来计算,它被定义在stddef.h头文件中。下面我们来计算一下上面代码中的结构体各个成员的偏移量:
这里写图片描述

下面我们来介绍一下第二个原则
原则二在经过第一原则分析后,检查计算出的存储单元是否为所有元素中最宽的元素的长度的整数倍,是,则结束;若不是,则补齐为它的整数倍。
第二个原则是为了避免当我们定义结构体数组时,可能会出现访问一个成员时要访问两块内存的情况,所以,编译器会把没有达到结构体最大字节的整数倍的内存浪费掉。
这里写图片描述

为什么需要内存对齐

内存对齐是一种消耗空间来换取时间的做法,没有内存对其我们可能访问一个成员变量需要对两块内存进行访问,这时非常影响效率的,而当有了内存对齐后,虽然我们是浪费掉一些内存空间,但我们访问一个成员变量只需要访问一块内存(每次访问最大的成员变量的内存)。另外,内存对齐还简化了形成处理器和内存系统之间接口的硬件设计。

发表评论

表情:
评论列表 (有 0 条评论,262人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C语言结构字节对齐原则

     为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的