【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.mzph.cn/news/865462.shtml

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

相关文章

【C++】多态详解

💗个人主页💗 ⭐个人专栏——C学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 一、多态概念 二、多态的定义及实现 1. 多态的构成条件 2. 虚函数 2.1 什么是虚函数 2.2 虚函数的重写 2.3 虚函数重写的两个…

PyPDF2拆分PDF文件为单个页面

本文目录 前言一、拆分成为单页1、代码解析2、处理效果图3、完整代码二、其它知识1、enumerate是什么① 语法② 功能③ 示例④ 更改起始索引前言 感觉之前写的不是很满意,为了充分满足付费用户的权益,所以打算把PyPDF2的各种类和用法都重新写一下,以便满足所有订阅用户的各…

transformer模型学习路线_transformer训练用的模型

Transformer学习路线 完全不懂transformer,最近小白来入门一下,下面就是本菜鸟学习路线。Transformer和CNN是两个分支!!因此要分开学习 Transformer是一个Seq2seq模型,而Seq2seq模型用到了self-attention机制&#xf…

三分钟看懂SMD封装与COB封装的差异

全彩LED显示屏领域中,COB封装于SMD封装是比较常见的两种封装方式,SMD封装产品主要有常规小间距以及室内、户外型产品,COB封装产品主要集中在小间距以及微间距系列产品中,今天跟随COB显示屏厂家中品瑞一起快速看懂SMD封装与COB封装…

使用高斯混合模型识别餐厅热点

使用 GMM 识别加拿大多伦多的直观餐厅集群(附 Python 代码) 聚类算法(例如 GMM)是一种有用的工具,可帮助识别数据中的模式。它们使我们能够识别数据集中的子组,从而提高你的理解或增强预测模型。在本文中&a…

DDR3(一)

目录 1 SDRAM1.1 同步动态随机存储器1.2 位宽1.3 SDRAM结构1.4 SDRAM引脚图 2 SDRAM操作指令2.1 读写指令2.2 刷新和预充电2.3 配置模式寄存器2.4 读/写突发2.5 数据屏蔽 SDRAM是DDR3的基础,在学习DDR3之前,我们先来学习一下SDRAM的相关知识。 1 SDRAM …

同样的APP为何在Android 8以后网络感觉变卡?

前言 在无线网络技术不断发展的今天,Wi-Fi已经成为了我们日常生活中不可或缺的一部分。无论是家庭娱乐、办公还是在线游戏,Wi-Fi都在提供着便捷的互联网接入服务。然而,在安卓8.1后,为了进一步延长安卓设备的待机时间。原生安卓(A…

推荐三款常用接口测试工具!

接口测试是软件开发中至关重要的一环,通过对应用程序接口进行测试,可以验证其功能、性能和稳定性。随着互联网和移动应用的快速发展,接口测试变得越来越重要。为了提高测试效率和质量,开发人员和测试人员需要使用专业的接口测试工…

【SCAU操作系统】期末复习简答及计算题例题解析

目录 一、写出下列英文缩写词在计算机系统中的英文或中文全名。 二、进程状态/调度/周转问题 (1)进程状态 (2)进程状态转换 (3)进程调度 (4)最短进程优先调度算法 三、逻辑地…

鸿蒙开发设备管理:【@ohos.runningLock (Runninglock锁)】

Runninglock锁 该模块主要提供Runninglock锁相关操作的接口,包括创建、查询、持锁、释放锁等操作。 说明: 本模块首批接口从API version 7开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 导入模块 import runningLock f…

经典资料分享:macOS设计指南(持续更新)

​MacOS设计指南是Mac应用设计必备的指导手册,学姐特提示完整指南文档给大家,原版中英文对照,实用方便查询。 因为文档内容太多,在后继的几个月会持续更新。本周更新内容为: 『MacOS设计指南-应用程序架构篇』 指南内容…

Vuex的基本使用

1.安装vuex npm i vuex3 2.引入 import Vuex from vuex 3.使用 Vue.use(Vuex) 4.在src下的目录创建store,新建index.js import store from ./store 5.编写index.js import Vue from vue import Vuex from vuex Vue.use(Vuex)//用于操作组件中的动作 const actions{a…

零知识学习之DPDK与RDMA(3)—— 认识DPDK(3)

接前一篇文章:零知识学习之DPDK与RDMA(2)—— 认识DPDK(2) 本文内容参考: 《Linux高性能网络详解 从DPDK、RDMA到XDP》 刘伟著 人民邮电出版社 https://blog.51cto.com/u_15301988/5181201 特此致谢&…

Shell Expect自动化交互(示例)

Shell Expect自动化交互 日常linux运维时,经常需要远程登录到服务器,登录过程中需要交互的过程,可能需要输入yes/no等信息,所以就用到expect来实现交互。 关键语法 ❶[#!/usr/bin/expect] 这一行告诉操…

昇思MindSpore学习笔记3-02热门LLM及其他AI应用--K近邻算法实现红酒聚类

摘要: 介绍了K近邻算法,记录了MindSporeAI框架使用部分wine数据集进行KNN实验的步聚和方法。包括环境准备、下载红酒数据集、加载数据和预处理、搭建模型、进行预测等。 一、KNN概念 1. K近邻算法K-Nearest-Neighbor(KNN) 用于分类和回归的非参数统计…

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

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

Spring中使用FactoryBean配置注入Bean

spring通过FactoryBean配置可以将第三方框架整合到Spring中来,FactoryBean配置如下: 写一个用于注于的实体类,如User,并对这个类写一个实现FactoryBean的中间类(UserFactoryBean) User类 /** *Description: *author…

粒子扩展卡尔曼滤波|MATLAB代码

粒子滤波PF与扩展卡尔曼滤波EKF结合 下载链接:https://download.csdn.net/download/callmeup/89512392 粒子滤波 粒子滤波是一种用于估计状态变量的非线性滤波方法。它通过引入一组粒子来近似表示概率分布,从而利用蒙特卡洛方法进行状态估计。粒子滤波的主要思想是根据系统…

什么是带有 API 网关的代理?

带有 API 网关的代理服务显著提升了用户体验和性能。特别是对于那些使用需要频繁创建和轮换代理的工具的用户来说,使用 API 可以节省大量时间并提高效率。 了解 API API,即应用程序编程接口,是服务提供商和用户之间的连接网关。通过 API 连接…

昂科烧录器支持MindMotion灵动微电子的32位微控制器MM32L052NT

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表,其中MindMotion灵动微电子的32位微控制器MM32L052NT已经被昂科的通用烧录平台AP8000所支持。 MM32L052NT使用高性能的ARM Cortex-M0为内核的32位微控制器,最高工作频率…