【C++】结构体内存对齐详解

规则

1.第一个成员在结构体变量偏移量为0 的地址处,也就是第一个成员必须从头开始。
2.其他成员的偏移量为对齐数**(该成员的大小 与 编译器默认的一个对齐数 中的较小值)**的整数倍。
3.结构体总大小对最大对齐数(通过最大成员来确定)的整数倍。

所有成员在内存中的位置是按照声明顺序决定的

代码解释

第一个和第三个规则好理解,上代码解释下第二个规则

#include<iostream>
#include<string>
#include<stddef.h>
using namespace std;#pragma pack(8) //修改默认对齐数为8struct A {char a;  char b;double c;
};struct B {char a;double b;char c;
};int main() {cout << "结构体A的大小:" << sizeof(A) << " a偏移-" <<offsetof(A, a) << " b偏移-" << offsetof(A, b) << " c偏移-" << offsetof(A, c) << endl;cout << "结构体B的大小:" << sizeof(B) << " a偏移-" <<offsetof(B, a) << " b偏移-" << offsetof(B, b) << " c偏移-" << offsetof(B, c) << endl;system("pause");
}

在这里插入图片描述

假设我们申请到的内存的初始编号为【000】

结构体A

基于第一个规则,第一个成员a的偏移为0,所以存储在【000】的内存中
成员b是一个char类型,该成员占用1个字节,而此时的编译器对齐数为8,根据规则2, 取两者的较小值就为1,所以成员b的偏移量应该为1的整数倍,所以成员b存储在【001】,偏移量就为1
同理,成员c的偏移量应该是8的整数倍,所以要存储在【008】-【015】,偏移量为8
所以结构体A实际占用了【000】-【015】的内存,大小为16,其中a在【000】,b在【001】,【002】-【007】没有存储数据,c在【008】-【015】

结构体B

成员a的偏移为0,所以存储在【000】的内存中
成员b的对齐数为8,所以要找到下一块以8的整数倍的内存,找到【008】,所以存储在【008 】-【015】的内存中,偏移为8
成员c的对齐数为1,所以存储在【016】,偏移为16
目前来看结构体B实际占用了17个字节,根据规则3,向上取8的整数倍,所以结构体B实际占用了24个字节,【000】-【023】,其中a在【000】,b在【008】-【015】,c在【016】,【001】-【007】和【017】-【023】没有存储内容

刚才是 编译器的对齐数 比 成员数据类型大 的情况,我们再看一个 编译器对齐数 小于 成员数据类型的情况

#include<iostream>
#include<string>
#include<stddef.h>
using namespace std;#pragma pack(4) //修改默认对齐数为4struct B
{char a;double b;char c;
};int main()
{B TempData;TempData.a = 'a';TempData.b = 12;TempData.c = 'c';cout << *(&(TempData.a)+12) << endl;system("pause");
}

这次我们修改了编译器的对齐数为4
成员a还是在【000】的位置,偏移为0
成员b是double类型,占用8个字节,编译器的对齐数是4,取二者的较小值就是4,所以b此时要存储在4的整数倍的地址上,【004】-【011】,偏移为4
成员c就存储在成员b之后,【012】
所以结构体b的大小就是16 (8的整数倍),a在【000】,b在【004】-【011】,c在【012】,【001】-【003】和【013】-【015】没有存储数据

成员数据可以直接根据偏移量来获取到,我们取到a的地址,然后再偏移12个字节就可以获取到c的地址
在这里插入图片描述

看完以上两个示例。内存对齐应该可以理解了,但仔细一想,为什么会有内存对齐,这不纯粹就是浪费空间么, 不对齐不是可以节省空间么

内存对齐的原因

平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于:为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。所以内存对齐能够提高访问效率。

解释一下性能原因, 现在机器分为32位和64位, 位数也就是CPU的字长, 也就是CPU一次能读取的数据大小, 64位就是8字节, 这里的CPU读取位数 你们可以和上面的 编译器的对齐位数 往一起想

如果没有内存对齐的情况, 我们以下面这个结构体为例, 如果你要读取到b, 那么需要先读取8个字节, 【000】-【007】,这里的【000】存储的是a,【001】-【007】存储的是b的一部分,这时CPU还要再读取一次【008】-【015】, 然后把【001】-【008】拼凑为b, 这里就读取了两次才获取到b

struct B {char a;double b;char c;
};

所以内存对齐本质上就是一种空间换时间的做法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/266799.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本科毕业设计:计及并网依赖性的分布式能源系统优化研究。(C语言实现)(内包含NSGA II优化算法)(二)

目录 前言 1、sofc函数 2、光伏板函数 3、集热场函数 4、sofc电跟随策略函数 5、二分法找sofc运行点函数 6、目标函数&#xff1a;成本 7、目标函数&#xff1a;二氧化碳排放量 8、目标函数&#xff1a;并网依赖性 前言 本篇文章介绍的是我的毕业设计&#xff0c;我将C…

[游戏开发][虚幻5]新建项目注意事项

鼠标右键点击Client.uproject文件&#xff0c;可以看到三个比较关键的选项&#xff0c; 启动游戏&#xff0c;生成sln解决方案&#xff0c;切换引擎版本 断点调试 C代码重要步骤 如果你想断点调试C代码&#xff0c;则必须使用使用代码编译启动引擎&#xff0c;你需要做几个操作…

java-ssm-jsp广播剧制作订阅系统

java-ssm-jsp广播剧制作订阅系统 获取源码——》公主号&#xff1a;计算机专业毕设大全

YOLOv5白皮书-第Y4周:common.py文件解读

YOLOv5白皮书-第Y4周:common.py文件解读 YOLOv5白皮书-第Y4周:common.py文件解读0.导入需要的包和基本配置1.基本组件1.1 autopad1.2 Conv1.3 Focus1.4 Bottleneck1.5 BottleneckCSP1.6 C31.7 SPP1.8 Concat1.9 Contract、Expand 2.重要类2.1 非极大值抑制&#xff08;NMS&…

makefileGDB使用

一、makefile 1、make && makefile makefile带来的好处就是——自动化编译&#xff0c;一旦写好&#xff0c;只需要一个make命令&#xff0c;整个工程完全自动编译&#xff0c;极大的提高了软件开发的效率 下面我们通过如下示例来进一步体会它们的作用&#xff1a; ①…

【rust】11、所有权

文章目录 一、背景二、Stack 和 Heap2.1 Stack2.2 Heap2.3 性能区别2.4 所有权和堆栈 三、所有权原则3.1 变量作用域3.2 String 类型示例 四、变量绑定背后的数据交互4.1 所有权转移4.1.1 基本类型: 拷贝, 不转移所有权4.1.2 分配在 Heap 的类型: 转移所有权 4.2 Clone(深拷贝)…

[ffmpeg] x264 配置参数解析

背景 创建 x264 编码器后&#xff0c;其有一组默认的编码器配置参数&#xff0c;也可以根据需要修改参数&#xff0c;来满足编码要求。 具体参数 可修改的参数&#xff0c;比较多&#xff0c;这边只列举一些常用的。 获取可以配置的参数 方式1 查看 ffmpeg源码 libx264.c…

apidoc接口文档的自动更新与发布

文章目录 一、概述二、环境准备三、接口文档生成1. 下载源码2. 初始化3.执行 四、文档发布五&#xff0c;配置定时运行六&#xff0c;docker运行七&#xff0c;优化方向 一、概述 最近忙于某开源项目的接口文档整理&#xff0c;采用了apidoc来整理生成接口文档。 apidoc是一个…

Java8 - LocalDateTime时间日期类使用详解

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&…

HarmonyOS—编译构建概述

编译构建是将应用/服务的源代码、资源、第三方库等&#xff0c;通过编译工具转换为可直接在硬件设备上运行的二进制机器码&#xff0c;然后再将二进制机器码封装为HAP/APP软件包&#xff0c;并为HAP/APP包进行签名的过程。其中&#xff0c;HAP是可以直接运行在模拟器或真机设备…

THINKPHP 跨域报错解决方案

报错&#xff1a;has been blocked by CORS policy: Response to preflight request doesnt pass access control check: No Access-Control-Allow-Origin header is present on the requested resource. 环境&#xff1a;thinkphp6 nginx 今天和VUE配合调用接口的时候发现跨…

utniy urp shinyssrr插件使用

文章目录 前言步骤1首先在URP的配置文件里添加SSR后处理2 修改RenderingPath为延迟渲染3 启用深度纹理4 为物体添加脚本 插件下载 前言 用来实现屏幕空间反射效果 unity 版本为2021.3.8LTS&#xff0c;低版本的untiy URP的参数设置位置z可能会不同 步骤 1首先在URP的配置文件…

【C语言】三子棋

前言&#xff1a; 三子棋是一种民间传统游戏&#xff0c;又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏规则是双方对战&#xff0c;双方依次在9宫格棋盘上摆放棋子&#xff0c;率先将自己的三个棋子走成一条线就视为胜利。但因棋盘太小&#xff0c;三子棋在很多时候会出现和…

Java-常用集合

Jva常用集合 一、Java 集合框架体系二、Collection接口和方法1. List接口List 接口主要实现类&#xff1a;ArrayListList 的实现类之二&#xff1a;LinkedListList 的实现类之三&#xff1a;Vector 2. Set接口Set 主要实现类&#xff1a;HashSetSet 实现类之二&#xff1a;Link…

抽象类与抽象方法

文章目录 抽象类抽象类的特点 抽象方法抽象方法的特点 模板设计模式模板设计模式能解决的问题示例 #抽象类与抽象方法 抽象类 用abstract关键字来修饰一个类时&#xff0c;这个类就叫抽象类。 public abstract 类名{... }抽象类的特点 1&#xff09;抽象类不能被实例化。 2&…

基于 LVGL 使用 SquareLine Studio 快速设计 UI 界面

目录 简介注册与软件获取工程配置设计 UI导出源码板级验证更多内容 简介 SquareLine Studio 是一款专业的 UI 设计软件&#xff0c;它与 LVGL&#xff08;Light and Versatile Graphics Library&#xff0c;轻量级通用图形库&#xff09;紧密集成。LVGL 是一个轻量化的、开源的…

[HackMyVM]靶场 Adria

kali:192.168.56.104 主机发现 arp-scan -l 靶机:192.168.56.108 端口扫描 nmap -p- 192.168.56.108 开启了 22 80 139 445端口 进入web 编辑 /etc/hosts&#xff0c;把192.168.56.108 adria.hmv添加进去重新访问 里面没什么有用的东西&#xff0c;注册需要邮箱&#xff0c;…

字典树基础,朴素字符串查找

字典树基础&#xff0c;朴素字符串查找 空间&#xff08;o(n*m)&#xff09; #include<bits/stdc.h> using namespace std; ​ const int N 2e6 9; int nex[N][26]; int cnt[N]; int idx 2; void insert(char s[]){int x 1;for (int i 0; s[i]; i){//判断x是否存在是…

Docsify部署IIS

什么是Docsify&#xff1f; 一个神奇的文档网站生成器。docsify 可以快速帮你生成文档网站。不同于 GitBook、Hexo 的地方是它不会生成静态的 .html 文件&#xff0c;所有转换工作都是在运行时。如果你想要开始使用它&#xff0c;只需要创建一个 index.html 就可以开始编写文档…

2024年腾讯云服务器优惠活动,3月份价格曝光可领代金券

腾讯云优惠活动2024新春采购节活动上线&#xff0c;云服务器价格已经出来了&#xff0c;云服务器61元一年起&#xff0c;配置和价格基本上和上个月没什么变化&#xff0c;但是新增了8888元代金券和会员续费优惠&#xff0c;腾讯云百科txybk.com整理腾讯云最新优惠活动云服务器配…