结构体内存对齐

server/2024/9/20 7:24:38/ 标签: 嵌入式, 内存

目录

  • 一、什么是结构体内存对齐
  • 二、为什么要结构体内存对齐
  • 三、对齐系数
  • 四、结构体对齐规则
    • 1、例一:文章开头的例子
    • 2、例二:稍微复杂的情况
    • 3、结合 union 和 struct
    • 4、结构体嵌套


一、什么是结构体内存对齐

进入讲解前,先看一段 C 代码:

struct Node1 {int a;char b;char c;
} node1[1024];struct Node2 {char b;int a;char c;
} node2[1024];

思考一下 node1node2 的大小分别为多少?

printf("The size of node1 is: %d\r\n", sizeof(node1));
printf("The size of node2 is: %d\r\n", sizeof(node2));

结果如下:

The size of node1 is: 8192
The size of node2 is: 12288

我是在 Windows 下 MinGW32 的 GCC 测试的

一样的成员属性,但 node1 只有 8K,而 node2 的大小却有 12K。

由此可见,结构体对齐,实质上就是内存对齐。

二、为什么要结构体内存对齐

为什么要结构体对齐,原因就是内存要对齐,原因是芯片内存的制造限制,是制造成本约束,是内存读取效率要求。

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,

  • 为了访问未对齐内存,处理器需要作两次内存访问;
  • 对齐内存访问仅需要⼀次访问。

假设一个处理器总是从内存中取 8 个字节,则地址必须是 8 的倍数。如果我们能保证将所有的 double 类型的数据的地址都对齐成 8 的倍数,那么就可以用一个内存操作来读或者写值了。否则,我们可能需要执行两次内存访问,因为对象可能被分放在两个 8 字节内存块中。

总体来说,结构体的内存对齐是拿空间来换取时间的做法。

三、对齐系数

对齐系数是指编译器在内存布局中对结构体成员进行对齐的要求。由于硬件访问内存的方式有一定的要求,结构体的对齐方式会影响内存的使用效率和访问速度。

在大多数编译器中,结构体对齐系数是通过编译器的编译选项或者特定的指令来指定的。对齐系数通常以字节为单位,表示结构体成员的起始位置必须是该字节数的整数倍。

注意,不同的平台,模数是不一样的。

struct Node3 {int a;double b;
} node3;printf("The size of node3 is: %d\r\n", sizeof(node3));
printf("node3.a address: %p\r\n", &node3.a);
printf("node3.b address: %p\r\n", &node3.b);

结果如下:

The size of node3 is: 16
node3.a address: 003CF1B8
node3.b address: 003CF1C0

可知,对齐系数就是 8.

当然,对齐模数是可以改变的,可以用预编译命令 #pragma pack(n),n=1,2,4,8,16(必须是 2 的幂次方)来改变这一系数,其中的 n 就是你要指定的“对齐系数”。

现在将上面的结构体改变一下:

#pragma pack(4)
struct Node3 {int a;double b;
} node3;
#pragma pack()

将它的对齐模数改为了 4,结果如下:

The size of node3 is: 12
node3.a address: 0042F1B8
node3.b address: 0042F1BC

四、结构体对齐规则

  1. 结构体的内存大小,并非其内部元素大小之和;
  2. 结构体变量的起始地址,可以被最大元素基本类型大小或者模数整除;
  3. 结构体的内存对齐,按照其内部最大元素基本类型或者模数大小对齐;
  4. 模数在不同平台值不一样,也可通过 #pragma pack(n) 方式去改变,其中 n 一定是 2 的幂次方,如 1,2,4,8,16 等;
  5. 如果空间地址允许,结构体内部元素会拼凑一起放在同一个对齐空间;
  6. 结构体内有结构体变量元素,其结构体并非展开后再对齐;
  7. unionbitfield 变量也遵循结构体内存对齐原则。

下面结合例子来看一下:

1、例一:文章开头的例子

对于本文一开始提到的例子,它们的内存对齐方式如下(这里就不以数组举例了):

struct Node1 {int a;char b;char c;
} node1;struct Node2 {char b;int a;char c;
} node2;

解释如下:

node1 中的元素 a 是 int 类型,按 4 个字节对齐,其地址位是 4 的整数倍;而 b 和 c 就按 1 字节对齐,就跟在 a 后面就行了。

node2 中 b 是按 1 个字节对齐,放在最前面;而 a 是按 4 个字节对齐,其地址位必须是 4 的整数倍,所以,只能找到个 +4 的位置;紧接着 c 就按 1 字节对齐,跟其后面。

2、例二:稍微复杂的情况

struct Node4 {char  a;short b;char  c;int   d;char  e;
} node4;

结果如下:

The size of node4 is: 16
node4.a address: 00E1F1C4
node4.b address: 00E1F1C6
node4.c address: 00E1F1C8
node4.d address: 00E1F1CC
node4.e address: 00E1F1D0

内存分布如下:

3、结合 union 和 struct

struct Node5 {int a;        union {char ua[9];      int ub;}u;      double b;  int c;
} node5;

如果 union 里的元素类型不一样,那就以最大长度的那个类型对齐了。

4、结构体嵌套

typedef struct {int a;char b;
} node1;struct Node11 {node1 nd1;char c;
} node11;typedef struct {short a;char b;
} node2;struct Node22 {node2 nd2;char c;
} node22;
The size of node11 is: 12
node11.nd1 address: 0028F1D4
node11.c address: 0028F1DCThe size of node22 is: 6
node22.nd2 address: 0028F1E0
node22.c address: 0028F1E4

可以看见,结构体内的结构体,结构体内的元素并不会和结构体外的元素合并占一个对齐单元。


http://www.ppmy.cn/server/117782.html

相关文章

DAY13信息打点-Web 应用源码泄漏开源闭源指纹识别GITSVNDS备份

#知识点 0、Web架构资产-平台指纹识别 1、开源-CMS指纹识别源码获取方式 2、闭源-习惯&配置&特性等获取方式 3、闭源-托管资产平台资源搜索监控 演示案例: ➢后端-开源-指纹识别-源码下载 ➢后端-闭源-配置不当-源码泄漏 ➢后端-方向-资源码云-源码泄漏 …

postgresql|数据库|pg_repack和idle_in_transaction_session_timeout参数的关系

一、问题描述 在使用pg_repack这个工具做数据库的表膨胀清理过程中,经常会遇到类似这样的警告: 这里的警告表明在膨胀治理的时候,此表遇到了事务阻塞,而此时我们有三种选择,第一个选择是等待该事务结束,第…

机器学习 vs. 深度学习

目录 引言 机器学习 深度学习 机器学习与深度学习的区别概览 引言 随着人工智能技术的发展,机器学习(Machine Learning)和深度学习(Deep Learning)成为了当今最热门的研究领域之一。尽管这两个术语经常被交替使用&…

【代码随想录训练营第42期 Day57打卡 - 图论Part7 - Prim算法与Kruskal算法

目录 一、Prim算法 二、题目与题解 题目:卡码网 53. 寻宝 题目链接 题解1:Prim算法 题解2:Prim算法优化 题解3:Kruskal算法 三、小结 一、Prim算法与Kruskal算法 Prim算法是一种贪心算法,用于求解加权无向图的…

构建高效 Python Web API:RESTful 设计与 GraphQL 实践

构建高效 Python Web API:RESTful 设计与 GraphQL 实践 在现代 Web 开发中,API 是前后端通信的核心枢纽,设计一个高效且易于扩展的 API 是保证系统良好运行的基础。本文详细探讨 RESTful API 的设计准则,如何生成 API 文档&#…

HCIP--<OSPF2>

目录 一,OSPF的不规则区域 1)远离骨干区域的非骨干区域 2)不连续骨干区域(和上面一样) 二,OSPF数据库表 三。优化OSPF的LSA(缺少LSA的更新量) [1]手工汇总:减少骨干区域的LSA [2]特殊区域&…

轨道列车舱门检测系统源码分享

轨道列车舱门检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

GitHub图床

GitHub图床 文章目录 GitHub图床图床介绍Github访问GitHub手动修改hostsgithub520 加速器创建账户创建仓库创建token PicGoTypora 图床介绍 图床 存放图片的地方 为什么设置图床呢 在我认识图床之前, 有一个问题 [^放在typora上面的图片, 其实是一个链接, 并且将图片存放在本地…

TS - tsconfig.json 和 tsconfig.node.json 的关系,如何在TS 中使用 JS 不报错

目录 1,前言2,二者关系2.1,使用 3,遇到的问题3.1,TS 中使用 JS 1,前言 通过 Vite 创建的 Vue3 TS 项目,根目录下会有 tsconfig.json 和 tsconfig.node.json 文件,并且存在引用关系…

51单片机+proteus+实验(I2C和蜂鸣器)

目录 1.蜂鸣器 1.1基本概念 1.1.1蜂鸣器的简介 1.1.2蜂鸣器的硬件原理 1.1.3蜂鸣器的音色 1.2代码 1.2.1不同音色驱动 1.2.2使用Music Encode1软件来生成音乐 1.3proteus仿真 2.I2C 2.1基本概念 2.1.1 I2C的基本概念 2.1.2 I2C的通讯时序 2.1.3AT24C02数据帧 ​编…

Qt_显示类控件

目录 一、QLabel 1、QLabel属性介绍 2、textFormat文本格式 3、pixmap标签图片 3.1 resizeEvent 4、QFrame边框 5、alignment文本对齐 6、wordWrap自动换行 7、indent设置缩进 8、margin设置边距 9、buddy设置伙伴 二、QLCDNumber 1、QLCDNumber属性介绍 2、实…

【AI大模型】ChatGPT模型原理介绍(下)

目录 🍔 GPT-3介绍 1.1 GPT-3模型架构 1.2 GPT-3训练核心思想 1.3 GPT-3数据集 1.4 GPT-3模型的特点 1.5 GPT-3模型总结 🍔 ChatGPT介绍 2.1 ChatGPT原理 2.2 什么是强化学习 2.3 ChatGPT强化学习步骤 2.4 监督调优模型 2.5 训练奖励模型 2.…

上海亚商投顾:沪指探底回升 华为产业链午后爆发

上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 沪指昨日探底回升,深成指、创业板指盘中跌逾1%,午后集体拉升翻红。华为产业链午后走强…

朴朴超市 签到 任务脚本

脚本主要用于自动化处理朴朴超市APP的签到和组队任务。以下是对脚本中主要方法的作用解析: 初始化和登录 - __init__: - 初始化类对象,设置用户信息和请求头,尝试获取并设置随机位置。 - get_AccessToken: - 使用`refresh_token`刷新并获取`access_token`,用于后续的A…

安卓玩机工具-----ADB与 FASTBOOT模式 图形化 多功能玩机刷机工具

工具说明 这款工具是英文版。易于使用的工具提供了用于运行 ADB 和 Fastboot 命令的图形用户界面。ADB 功能包括旁加载、安装和卸载应用程序、测试设备以及重新启动到不同的模式。可以使用 fastboot 命令进行设备管理;其中包括检查 Antirollback 和 active slots 等变…

Nginx:高性能的Web服务器与反向代理

在当今的互联网世界中,Web服务器的选择对于网站的性能、稳定性和安全性至关重要。Nginx(发音为“engine X”)凭借其卓越的性能、丰富的功能集和灵活的配置选项,成为了众多网站和应用程序的首选Web服务器和反向代理。本文将深入探讨…

Canal+RabbitMQ数据同步环境配置

Canal 是阿里巴巴开发的开源工具,主要用于解析 MySQL 的 binlog 日志,从而实现数据同步。Canal 会模拟 MySQL 从库的协议,订阅主库的 binlog,从而获取数据库的变更信息。 将 Canal 解析到的 MySQL 数据库变更消息通过 RabbitMQ 分…

详细分析Uniapp中的轮播图基本知识(附Demo)

目录 前言1. 基本知识2. Demo2.1 基本2.2 自定义分页2.3 自定义动画 3. 扩展 前言 先看代码示例&#xff1a; 实现了一个带有分页指示器的轮播图组件 <template><view class"work-container"><!-- 轮播图 --><uni-swiper-dot class"uni…

flask框架

Flask 1 flask简介 我们之所以在浏览器中输入localhost:8080然后就可以把webapps下面的项目文件以浏览器的方式打开&#xff0c;功臣在与tomcat。python语言写的项目&#xff0c;转换为web&#xff0c;Flask框架 轻量级web应用框架。 环境准备&#xff1a; pip install fl…

SSHamble:一款针对SSH技术安全的研究与分析工具

关于SSHamble SSHamble是一款功能强大的SSH技术安全分析与研究工具&#xff0c;该工具基于Go语言开发&#xff0c;可以帮助广大研究人员更好地分析SSH相关的安全技术与缺陷问题。 功能介绍 SSHamble 是用于 SSH 实现的研究工具&#xff0c;其中包含下列功能&#xff1a; 1、针…