计算结构体大小:内存对齐详解

        前言:不管在面试还是在升学的路上,内存对齐永远是结构体和联合体的热门考点,对于同样的结构体成员,他们相互之间的顺序位置不同就会导致整个结构体大小的不同,因此计算结构体联合体的字节大小就成为了一个有效的考点

目录

一.什么是内存对齐

二.怎么对齐的

使用 offsetof 宏来观察

结构体S1

结构体S2 

三.如何计算对齐

第一步:

第二步:

第三步:

第四步:

四.练习题


一.什么是内存对齐

在解决这个问题之前,我们先看一组代码,大家可以思考思考会输出什么:

//结构体1
struct S1
{char c1;int i;char c2;
};//结构体2
struct S2
{char c1;char c2;int i;
};printf("%zd\n", sizeof(struct S1));
printf("%zd\n", sizeof(struct S2));

        我们可以看到俩个结构体的成员类型都是一模一样的,唯独不同的是成员直接的相互顺序不同,按道理来说应该输出的是同一个值,那结果真是这样吗,我们继续往下走

输出结果:

        结果非常的出人意料啊,他们的字节大小居然不一样,造成这样现象的原因就是因为存在结构体内存对齐的情况,接下来我们就来探索一下什么是结构体内存对齐以及如何计算它

二.怎么对齐的

使用 offsetof 宏来观察

什么是 offsetof 宏,我们打开 cplusplus 官网:

offsetof - C++ Reference (cplusplus.com)

        通过查询资料得知,offsetof 是用来计算结构体中成员单位相较于起始位置的偏移量的一个宏,具体使用如下

结构体S1

	//查看S1的成员的偏移量printf("%zd\n", offsetof(struct S1, c1));printf("%zd\n", offsetof(struct S1, i));printf("%zd\n", offsetof(struct S1, c2));

 输出结果如下:

那我们就根据图示画出内存中的大概模型

结构体S2 

同样的对结构体 S2 也做这样的处理

	printf("%zd\n", offsetof(struct S2, c1));printf("%zd\n", offsetof(struct S2, c2));printf("%zd\n", offsetof(struct S2, i));

输出结果:

根据图示画出内存中的大概模型

我们将俩个模型进行比较,并且结合输出观察

我们会发现

  • 在结构体 S1 中浪费了很多空间,在char c1 后浪费了 3 个字节的空间,在char c2 后浪费了 3 个字节的空间 
  • 在结构体 S2 中,char c1 后并没有浪费空间,而在 char c2 后浪费了 2 个字节的空间

 而这就是因为受到了结构体对其数的影响

三.如何计算对齐

首先得掌握结构体的对齐规则:

  1. 第一个成员在与结构体变量偏移量为 0 的地址处
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值(VS中默认的值为8 )
  3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

我们具体拿结构体 S1 来进行演示说明

第一步:

        第一个成员在与结构体变量偏移量为0的地址处

第二步:

        放置 int i 大小为 4 个字节和 VS 默认的对齐数 8 相比,取较小的数 4,所以下一个元素 int i 对齐到从起始位置数第 4 个单元的位置

第三步:

        放置 char c2 数据,char 大小为1个字节和 VS 默认的 8 相比,取较小的数 1 ,对齐数就是 1

第四步:

        结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍,在这个结构体里面,3 个成员的大小分别为 1, 4, 1,取最大值 4,所以这个结构体的大小必须是 4 的整数倍,我们已经使用了 9 个字节了,那 4 的最小整数倍就是 12,所以结构体 S1 的总大小为 12

四.练习题

        这里博主留下俩道练习题,有兴趣的朋友们可以自己尝试算一算俩个结构体分别占多大的字节空间,对于题目的见解,也欢迎各位将自己的思路和答案打在评论区内,大家一起讨论学习

struct S3
{double d;char c;int i;
};
struct S4
{char c1;struct S3 s3;double d;
};

本次的分享就到此为止了,如果你有不同的见解,欢迎在评论区相互交流,感谢您的支持

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

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

相关文章

linux 清除卸载jenkins

1、停服务进程 查看jenkins服务是否在运行,如果在运行,停掉 查看服务 ps -ef|grep jenkins 停掉进程 kill -9 XXX2、查找安装目录 find / -name "jenkins*"3、删掉相关目录 删掉相关安装目录 rm -rf /root/.jenkins/# 删掉war包 rm -rf /…

关于MATLAB R2022b中MATLAB function没有edit data选项的解决办法

问题描述 在MATLAB 2022b的simulink中双击MATLAB function,出来的是这个界面,而不是跳转到MATLAB的编辑窗口。因此就找不到edit data选项,没法完成新建data store memory 全局变量。 解决办法: 点击 编辑数据 按钮 在弹出的窗…

LiveGBS流媒体平台GB/T28181功能-海康大华摄像头接入无法语音对讲通道为0无法播放时候如何抓包分析windows抓包和Linux抓包

LiveGBS通道数为0无法播放的时候如何抓包分析windows抓包和Linux抓包 1、第一步:抓包工具准备1.1、Linux1.2、windows 2、第二步:找到设备出口ip3、第三步:执行命令抓设备出口ip3.1 Linux3.2 Windwos 4、第四步:触发相关页面操作4…

【产品运营】如何做好B端产品规划

产品规划是基于当下掌握的多维度信息,为追求特定目的,而制定的产品资源投入计划。 产品规划是基于当下掌握的多维度信息(客户需求、市场趋势、竞争对手、竞争策略等),为追求特定目的(商业增长、客户满意等&…

xcode15下载ios17模拟器失败

升级到xcode15后需要安装ios17模拟器 但是在下载过程中会遇到报错 如下图这种 网上搜索了一下发现有人遇到过无法下载的问题,并且在apple官网也有人提出类似问题 https://developer.apple.com/forums/thread/737648 解决方案就是从https://developer.apple.com/do…

HarmonyOS开发:解决DevEco Studio低版本导入高版本项目运行失败问题

前言 基于DevEco Studio 4.0 Beta2,hvigorVersion为3.0.2,开发了一个项目,上传到了远程仓库,当同事下载后,却始终无法运行,频繁报错,由于API都是使用的9,第一感觉就是开发环境不同&a…

Unity-Input System新输入系统插件学习

1.键盘、鼠标操作 using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UI;public class NewInputSystem : MonoBehaviour {public float SpaceKeyValue;public float RightMouseValue;public…

LeetCode 接雨水 双指针

原题链接: 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 题面: 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 1: 输入&#xff1a…

CSS实现围绕按钮边框转圈的光线效果

CSS实现围绕按钮边框转圈的光线效果&#xff0c;可以自由改变按钮的光线渐变颜色和按钮边框颜色&#xff0c;背景色等。 效果图&#xff1a; 实现完整代码&#xff1a; <template><view class"btnBlock"><view class"btnBian"></vi…

win11怎么查看之前连过的wifi密码

首先进入到设置 然后就可以看到之前连接过的WIFI&#xff1a; 选一个想要知道密码的WIFI点进去看到如下页面&#xff1a; 然后点击“显示”即可查看密码

Redis 数据类型底层原理

String 内部编码有三种&#xff1a;int、embstr、raw int&#xff1a;如果一个字符串对象保存的是整数值&#xff0c;并且这个整数值可以用 long类型来表示(不超过 long 的表示范围&#xff0c;如果超过了 long 的表示范围&#xff0c;那么按照存储字符串的编码来存储&#xf…

kafka安装部署,和基本操作

kafka下载地址&#xff1a;Apache Kafka 我这里下载3.5.1 ​ 2、通过rz命令上传到linux服务器 3、解压 tar -zxvf kafka_2.12-3.5.1.tgz 4、在config目录下修改配置文件server.properties 主要修改这两处&#xff1a; #监听的端口advertised.listenersPLAINTEXT://自己…

java spring cloud 企业电子招标采购系统源码:营造全面规范安全的电子招投标环境,促进招投标市场健康可持续发展

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

uniapp实现表格冻结

效果图如下&#xff1a; 思路&#xff1a; 1.由于APP项目需要&#xff0c;起初想去插件市场直接找现成的&#xff0c;结果找了很久没找到合适的&#xff08;有的不支持vue2有的不能都支持APP和小程序&#xff09; 2.后来&#xff0c;就只能去改uni-table源码了&#xff0c;因…

【面试高高手】——Spring(12题)

文章目录 1.Spring是什么&#xff1f;2.为什么需要Spring?3.说下你对Spring的AOP、IOC的理解&#xff1f;4.基于java的AOP实现有哪些&#xff1f;5.AOP的原理&#xff1f;6.如何使用Java实现动态代理?7. Spring AOP和AspectJ AOP有什么区别&#xff1f;8.SpringAOP通知类型&a…

联想详解AI导向基础设施 “软硬一体”赋能四大场景

9月25日&#xff0c;联想在杭州举办以“全栈智能 全程陪伴”为主题的新IT思享会&#xff0c;集中展示了联想基于新IT架构的全栈智能产品与服务&#xff0c;引领行业智能变革的强大实力。 当前&#xff0c;以ChatGPT为代表的AI模型席卷全球&#xff0c;不仅实现了AI技术质变性突…

电路常见的通信接口

1,TTL/232/485/422简介 串口 串口通信(Serial Communication)&#xff0c; 是指外设和计算机间&#xff0c;通过数据信号线 、地线、控制线等&#xff0c;按位进行传输数据的一种通讯方式。是我们在硬件调试过程中最常见的一种通信方式。比如开发板和电脑之间&#xff0c;想要…

如何更改注册表使系统暂停更新时间延长

1、创建一个文本文件&#xff0c;命名为&#xff1a;“stopupdate.reg”&#xff0c;然后用记事本或者代码编辑器打开&#xff0c;复制以下代码&#xff1a; Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings] "F…

高手必备!电脑剪辑视频的实用方法

随着数码时代的到来&#xff0c;越来越多的人开始使用电脑剪辑视频。电脑剪辑视频不仅可以为日常生活留下美好回忆&#xff0c;还可以为专业人士提供更多的创作可能性。在本文中&#xff0c;我们将介绍两种电脑剪辑视频的方法&#xff0c;不需要专业技能&#xff0c;只需要一台…

嵌入式MCU都有什么高级用法?

嵌入式MCU都有什么高级用法&#xff1f; 您举的几个例子&#xff0c;确实是MCU外设的一些高端玩法。只是不知道您是否想过&#xff0c;既然这些机制是被 人设计出来的&#xff0c;那它就是种标准用法。从微控制器的发展历程来看&#xff0c;许多硬件机制都是有了实际 需求后才…