野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 11417|回复: 3

C语言struct结构体内存对齐及其原则

[复制链接]
发表于 2020-5-13 20:15:59 | 显示全部楼层 |阅读模式

] 本帖最后由 Yuhailong 于 2020-5-13 20:33 编辑 [/i]

[md]从别处搬来的,给大家分享一下

一、存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:

(1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) (2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。

二、 对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:

(1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。 (2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。

为什么?

但是编译器为什么要这么做,以下是我的理解。

为什么要对齐?

因为在32位操作系统(虽然64位操作系统,但是为了保证兼容性,编程仍然主要考量32位)中,数据总线是32位,地址总线是32位。 地址总线是32位,意味着寻址空间是按4递增的;数据总线32位意味着一次可读写4byte。 考虑这样一个结构体

struct stu1
{

  char c1;
  int i;
  char c2;
}

1.png

不对齐就意味着,当我们执行stu1.i 时,需要读取内存两次。而对齐后,就只需要读取一次,众所周知,I/O操作是很耗时的,编译器做出对齐的选择也就好理解。

为什么不完全按照4字节对齐的?

既然对齐可以避免上述的问题,为什么不将所有存储小于4byte的数据类型(char, short等)统统按4byte对齐呢? 考虑这样一个结构体

struct stu2
{
  char c;
  short s;
  int i;
  double d;
}

2.png

为什么编译器采用B方案,而不采用A方案? 还是因为32数据线一次读取4个字节, 采用方案A,读取stu2.c,或者stu2.s,要一次读取4个byte,再舍弃无关内存的数据。 采用方案B,读取stu2.c,或者stu2.s,也是要一次读取4个byte,再舍弃无关内存中的数据。 同样的I/O操作,相比之下,明显方案B更节省内存。

补充: 如上图中,所示8字节的数据类型,比如double, long long,必须要读取两次内存。

回复

使用道具 举报

发表于 2020-5-14 15:50:16 | 显示全部楼层
多谢分享
回复

使用道具 举报

发表于 2020-5-24 15:05:32 来自手机 | 显示全部楼层
学习了。原子论坛上每日一题出了道这种题。
回复 支持 反对

使用道具 举报

发表于 2020-5-28 17:18:40 | 显示全部楼层
谢谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-25 18:24 , Processed in 0.035037 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表