【C语言】手撕结构体内存对齐

©作者:末央&

©系列:C语言初阶(适合小白入门)
©说明:以凡人之笔墨,书写未来之大梦

在这里插入图片描述

目录

  • 结构体对齐规则
  • 结构体大小计算 - 三步曲

结构体对齐规则

怎么计算结构体的内存大小。这就涉及到结构体内存对齐的问题。

  1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处
  2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。
  3. 对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的较⼩值。
    • VS 中默认的值为 8 (可以用#pragma pack(N)预编译命令修改默认对齐数)#pragma pack()//取消设置的默认对齐数,还原为默认
  4. Linux中 gcc 没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
  5. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的整数倍
  6. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构
    体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。

结构体大小计算 - 三步曲

知道了结构体内存对齐规则,我们就可以计算结构体的大小了。计算结构体的大小可分为三个步骤。我们拿下面这个结构体举例

struct S
{
	double d;
	char c;
	int i;
};

第一步:找出每个成员变量的大小将其与编译器的默认对齐数相比较,取其较小值为该成员变量的对齐数。
在这里插入图片描述
第二步:根据每个成员对应的对齐数画出它们在内存中的相对位置。
在这里插入图片描述
第三步:通过最大对齐数决定最终该结构体的大小。
通过图我们可以知道,绿色部分(double d成员占用)+红色部分(char c成员占用)+紫色部分(int i成员占用)+红色与紫色之间的白色部分(浪费掉了)总共占用了16个字节的内存空间。
我们需要将它们总共占用的内存空间(16)与结构体成员的最大对齐数(8)相比较,结构体的总大小为最大对齐数的整数倍,此时16正好是8的整数倍,所以该结构体在VS编译器下的大小就16个字节。即创建一个该类型的结构体变量,内存需为其开辟16个字节的内存空间。

注意:大多数情况下,成员变量已经占用的总字节个数并不一定正好为其成员变量中的最大对齐数的整数倍,这时我们需要将其扩大为最大对齐数的整数倍。

为什么存在内存对齐?
平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些平台只能在某些地址处取得某些特定类型的数据,否则抛出硬件异常。
比如,当一个平台要取一个整型数据时只能在地址为4的倍数的位置取得,那么这时就需要内存对齐,否则无法访问到该整型数据。

性能原因: 数据结构(尤其是栈)应该尽可能的在自然边界上对齐。原因在于,为了访问未对齐内存,处理器需要作两次内存访问;而对齐的内存访问仅需一次。

在画图时可能有博友会想,内存这么重要,在进行内存对齐的时候怎么还有内存被白白浪费掉呢?
现在看来,其实结构体的内存对齐是拿空间来换取时间的做法。

设计结构体时的技巧
其实在我们设计结构体的时候,如果结构体成员的顺序设计得合理的话,是可以避免不必要的内存消耗的。
两个结构体的成员变量相同,但是成员变量的顺序不同,可能就会出现结构体的大小不同的情况:

struct S1
{
	char a;
	char b;
	int c;
};//结构体1
struct S2
{
	char a;
	int c;
	char b;
};//结构体2

  我们可以看到,结构体1和结构体2的成员变量一模一样,可是当我们按照内存对齐规则来计算两个结构体的大小的时候,会发现两个结构体的大小不一样,在VS编译器下第一个结构体大小为8,第二个结构体大小为12。

可以见得,结构体成员变量的顺序不同,可能会造成内存不必要的损失。将占用空间小的成员尽量集中在一起,可以有效地避免内存不必要的浪费。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

项目实战--MySQL实现分词模糊匹配

一、需求描述 推广人员添加公司到系统时,直接填写公司简称,而公司全称可能之前已经被添加过,为防止添加重复的公司,所以管理员在针对公司信息审批之前,需要查看以往添加的公司信息里是否有相同公司。 二、方案 技术…

项目2:API Hunter 细节回顾 -1

一. 接口调用 对于开发者来说,接口的调用应当是方便快捷的,而且出于安全考虑,通常会选择在后端调用第三方 API,避免在前端暴露诸如密码的敏感信息。 若采用 HTTP 调用方式: HttpClientRestTemplate第三方库&#xf…

【JavaWeb】登录校验-会话技术(一)Cookie与Session

登录校验 实现登陆后才能访问后端系统页面,不登陆则跳转登陆页面进行登陆。 首先我们在宏观上先有一个认知: HTTP协议是无状态协议。即每一次请求都是独立的,下一次请求并不会携带上一次请求的数据。 因此当我们通过浏览器访问登录后&#…

py黑帽子学习笔记_burp

配置burp kali虚机默认装好了社区版burp和java,其他os需要手动装 burp是用java,还得下载一个jython包,供burp用 配apt国内源,然后apt install jython --download-only,会只下载包而不安装,下载的目录搜一…

【JVM-05】Java内存区域(运行时数据区)、对象创建过程、内存布局

【JVM-05】Java内存区域即运行时数据区、对象创建过程、内存布局 1. 介绍下Java内存区域(运行时数据区)1.1 程序计数器(线程私有)1.2 虚拟机栈(线程私有)1.3 本地方法栈(线程私有)1.4 Java堆(线程共享)1.5 方法区(线程共享)1.5.1 方法区和永久代的关系1.5.2 常用参数1.5.3 为什…

用随机森林算法进行的一次故障预测

本案例将带大家使用一份开源的S.M.A.R.T.数据集和机器学习中的随机森林算法,来训练一个硬盘故障预测模型,并测试效果。 实验目标 掌握使用机器学习方法训练模型的基本流程;掌握使用pandas做数据分析的基本方法;掌握使用scikit-l…

AWS的收费方式与计费项目

AWS(亚马逊云服务)是全球领先的云计算服务提供商,为各种规模和类型的企业提供了广泛的云计算服务。AWS的收费方式和计费项目是许多用户关心的问题,因为了解这些信息有助于企业更好地规划和控制成本。本文将介绍AWS的收费方式和常见…

MobileVitv1替换yolov8主干网络

一、原理介绍 MobileViT模型是为移动设备设计的轻量级、通用目的视觉变换器。它融合了卷积神经网络(CNN)和视觉变换器(ViT)的优势,旨在在保持高效性能的同时减少模型参数和降低延迟。以下是关于MobileViT模型的主要原理…

MATLAB中findall用法

目录 语法 说明 示例 查找具有可见或隐藏句柄的图窗 查找句柄处于隐藏状态的对象 查找 Text 对象 提示 findall的功能是查找所有图形对象。 语法 h findall(objhandles) h findall(objhandles,prop1,value1,...,propN,valueN) 说明 h findall(objhandles) 返回 ob…

电脑提示你的msvcr100.dll丢失要如何解决?一键修复msvcr100.dll的解决方法

电脑提示你的msvcr100.dll丢失要如何解决?首先我们就要了解msvcr100.dll这个文件,了解前因后果,这样我们才能知道使用什么方法去修复它。今天主要就是来给大家详细的讲解一下msvcr100.dll文件,并且教各种的修复方法,每…

excel表格如何换行,这几个操作方法要收藏好

Excel表格作为一款强大的数据处理工具,在日常工作和生活中被广泛应用。当需要在单元格内显示较长的文本内容或使数据更加清晰易读时,我们需要掌握一些换行技巧。下面将介绍几种常用的Excel换行方法: 一、使用快捷键换行 1、首先,…

介绍一些好玩且实用的开源的AI工具

介绍一些好玩且实用的开源的AI工具 随着人工智能技术的迅猛发展,开源社区涌现出了许多关于AI的项目,这些项目不仅展示了技术的创新力,也为开发者提供了丰富的工具和资源。本文将介绍几个既有趣又实用的开源人工智能工具,它们不仅…

前端Web开发HTML5+CSS3+移动web视频教程 Day4 CSS 第2天

P44 - P 四个知识点: 复合选择器 CSS特性 背景属性 显示模式 复合选择器 复合选择器仍然是选择器,只要是选择器,作用就是找标签。复合选择器就是把基础选择器进行组合使用。组合了之后就可以在大量的标签里面更快更精准地找标签了。找…

轻度图像处理工具,匹敌photoshop

一、简介 1、一款功能强大的在线图片编辑工具,用户可以将其安装为渐进式网页应用(PWA)。它提供了与 Photoshop 相似的核心功能,能够满足大多数图像编辑需求,非常适合那些不愿或无法安装 Photoshop 的用户。即使使用免费版本,用户也能享受所有功能,是轻度图像处理的理想选…

20240703在飞凌OK3588-C开发板上刷Rockchip原厂的Buildroot20220811

20240703在飞凌OK3588-C开发板上刷Rockchip原厂的Buildroot20220811 2024/7/3 18:25 详细的刷机LOG: [BEGIN] 2024/7/3 18:18:49 rootRK3588:/# DDR Version V1.07 20220412 LPDDR4X, 2112MHz channel[0] BW16 Col10 Bk8 CS0 Row16 CS1 Row16 CS2 Die BW16 Size204…

【高级篇】第9章 Elasticsearch 监控与故障排查

9.1 引言 在现代数据驱动的应用架构中,Elasticsearch不仅是海量数据索引和搜索的核心,其稳定性和性能直接影响到整个业务链路的健康度。因此,建立有效的监控体系和掌握故障排查技能是每一位Elasticsearch高级专家的必备能力。 9.2 监控工具:洞察与优化的利器 在Elastics…

MySQL加个索引都可能丢数据,这个坑你知道吗?

前言 近期,我们收到一位数据库运维小伙伴的咨询,他们有一个MySQL 5.6的数据库,需要对核心支付表做DDL加索引,咨询我们如何加索引更优雅。基于DBA经验,给表添加索引主要有以下几种方式: 用MySQL原生的DDL语…

BeautifulSoup 类通过查找方法选取节点

BeautifulSoup 类提供了一些基于 HTML 或 XML 节点树选取节点的方法,其中比较主流 的两个方法是 find() 方法和 find_all() 方法。 find() 方法用于查找符合条件的第一个节点; find_all() 方法用于查找所有符合条件的节点,并以列表的…

分页导航DOM更新实践:JavaScript与jQuery的结合使用

分页导航DOM更新实践:JavaScript与jQuery的结合使用 在Web开发中,分页导航是展示大量数据时不可或缺的UI组件。合理的分页不仅可以提高应用性能,还能优化用户体验。本博客将通过一个实际的DOM结构和模拟数据,讲解如何使用JavaScr…

计算机网络部分知识点整理

停止等待协议的窗口尺寸为 1。 √以太网标准是IEEE802.3TCP/IP四层,OSI模型有7层,地址解析协议 ARP 在 OSI 参考七层协议属于数据链路层,在TCP/IP 协议属于网络层,ARP作用:将 IP 地址映射到第二层地址,交换…