C语言之结构体内存对齐与内存的简单理解

news2025/1/19 15:05:43

文章目录

  • 内存单元的理解
  • 结构体中内存对齐的规则
  • 为什么会存在内存对齐


一、内存单元的理解

首先先要介绍一下C语言中一些常见的存储单元

    bit       存放一个二进制位
    Byte   1Byte = 8 bit
    KB     1KB   = 1024 Byte
    MB     1MB   = 1024 KB
    GB     1GB   = 1024 MB
    TB     1TB   = 1024 GB
    PB     1PB   = 1024 TB

        一个内存单元的大小占一个字节(Byte)。内存单元是一片连续的空间,对其的编号也是连续的。

如下图所示:

        接下来,我们来探讨一下地址编号是如何产生的:

        其实,在我们的计算机上,存在着这样的一种物理的电线,叫地址线。地址线一旦通电以后,就会产生电信号,形成高电平或者低电平。高低电平信号可以转换成数字信号,对应的就是1或者0。32位机器上有32根地址线,32根地址线通电后32个电平信号就可以转换成对应的32位的01二进制序列。

         从上图可以看到,32根地址线产生的地址编号总共就有2^{32}个。假设32个0序列用来管理上上图中0编号所指向的内存单元,31个0序列和最后的一个1所组成的序列用来管理1号所指向的内存单元,以此类推。这样,物理电线上所产生的电信号转换成的数字信号就可以被用来管理内存单元。也就是说,32位机器下就可以管理就可以管理2^{32}个Byte大小的内存,也就是4GB大小的内存。

二、结构体中内存对齐的规则

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


2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。(VS中默认的对齐数为8)


3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。


4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

 下面我将对这四条规则进行解释:

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

首先我们应理解什么是偏移量,见下图:


        假定由结构体S1创建出的s1在内存中的起始位置是图中所指向的横线,那么其下面的第一个存储单元的偏移量就是0,s1的第一个成员就从偏移量为0这个存储单元开始存储。

        2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。(VS中默认的对齐数为8)

        如图所示:c1是s1的第一个成员,存放在偏移量为0处,s1的第二个成员i的类型为int,大小为4个Byte,因为4小于8,所以i这个变量应该从偏移量为4的倍数处开始存放,存放4个Byte。最后c2的大小为1,从偏移量为1的倍数处开始存放,即紧跟着i变量存储即可。

3.结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。

        以上图中的S1来举例,其三个成员的类型分别为char,int,char,类型大小分别为1,4,1,所以所有变量类型最大者即为int,其大小为4Byte,小于VS的默认对齐参数(8Byte),所以最大对齐数为4,即创建出来的结构体变量s1的大小必须为4的倍数。从上图可知,此时s1已经占用了9个Byte,但还需向内存申请3个Byte大小的空间,构成12个Byte大小的空间,即s1的大小占12个Byte。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

         由上图以及两个结构体成员可知,S3的最大默认对齐数是8,所以s3的第一个成员要从偏移量为8的位置开始存放,其他存放规则与上面三条规则相同,最终S4的大小占32个Byte。

三、为什么会存在内存对齐

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

为什么未对齐的内存,处理器需要作两次内存访问呢?见下图:

 

在32位机器下,一次可以访问4个Byte,假设不采用内存对齐的方式,int类型的变量前有一个char类型的变量c,那么处理器要完全访问到i,第一次需要先访问c变量以及i变量的前三个字节,第二次再访问i的最后一个字节,这样就需要访问两次才能完全访问完i。

总体来说:

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

 那在设计结构体的时候,我们既要满足对齐,又要节省空间,我们应该:

让占用空间小的成员尽量集中在一起。

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

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

相关文章

Linux对文件夹操作(复制,移动)

Linux对文件夹操作(复制,移动) 复制文件夹cp cp -a vue vue-copy将vue 文件夹下面的所有文件,复制到同目录下vue-copy文件夹下面 -a:相当于 -d、-p、-r 选项的集合,这几个选项我们一一介绍;-d:如果源文件为软链接(…

数据库开发(Sqlite)

1、数据库开发 1.1 数据与数据管理 什么是信息?   信息是指对现实世界存在方式或运动状态的反应。 什么是数据?   数据是指存储在某一媒体上,能够被识别的物理符号;   数据的概念在数据处理领域已经被大为拓宽&#xff0c…

qt5.14.2 独立msvc环境搭建(不安装vs)

一般情况下msvc下的qt开发,无论你是用qtcreator还是vs都推荐安装对应vs版本,这样是最省事和便捷的,但在有些情况下不便安装vs但项目又需要使用msvc,则可以只安装msvc c编译器,步骤如下: 备注:文…

【Spring Clound】Feign底层原理分析-自动装载动态代理

文章目录前言1、什么是Feign?2、为什么要使用Feign?3、Feign依赖注入原理3.1、Feign自动装载3.2、FeignClientFactoryBean#getObject4、总结前言 是一个HTTP请求调用轻量级框架,可以以Java接口注解的方式调用HTTP请求,而不用像Ja…

Lunabot一款无需密钥魔法就能使用到ChatGPT的浏览器工具

Lunabot 简介 Lunabot是一款跨平台的ChatGPT助手,支持主流浏览器上的任意网页,可以快速处理各种任务,提高您的工作效率。使用 Lunabot,您可以轻松选择文本并使用快速命令和提示来快速处理任务,同时还可以保存永远不会…

Node【二】NPM

文章目录🌟前言🌟NPM使用🌟NPM使用场景🌟NPM的常用命令🌟NPM命令使用介绍🌟 使用NPM安装模块🌟 下载三方包🌟 全局安装VS本地安装🌟 本地安装🌟 全局安装&…

研读Rust圣经解析——Rust learn-5(所有权,强大的String)

研读Rust圣经解析——Rust learn-5(所有权,强大的String)所有权栈和堆相同点栈堆所有权规则作用域StringString创建String创建空字符串从字符串字面量创建(将&str转化为String)str特点创建str所有权转移String源码深克隆clone…

Matplotlib基本图形使用折线图-柱状图-散点图-饼图的完整代码含示例

目录 Matplotlib基本折线图的使用 1. 导入matplotlib库 2. 准备数据 3. 绘制折线图 4. 加上标签和标题 5. 自定义样式 6. 完整代码 ​编辑 绘制散点图 导入 matplotlib 库和 numpy 库 准备数据 绘制散点图 ​编辑 绘制饼图 导入 matplotlib 库和 numpy 库 准备数…

JS尺寸相关

文章目录元素偏移量 offset 系列offset 系列常用属性offset 与 style 区别获取鼠标在盒子内的坐标模态框放大镜效果元素client 系列元素client系列属性元素滚动 scroll 系列元素 scroll 系列属性页面被卷去的头部兼容性解决方案监听滚动效果仿淘宝固定侧边栏缓动动画筋斗云案例…

实战打靶集锦-015-djinn3

提示:本文记录了作者一次曲折的打靶提权经历 目录1. 主机发现2. 端口扫描3. 服务枚举4. 服务探查4.1 Lighttpd探查4.1.1 浏览器探查4.1.2 EXP搜索4.1.2.1 CVE-2019-110724.1.2.2 CVE-2018-190524.2 Werkzeug探查4.2.1 浏览器探查4.2.2 EXP搜索4.2.2.1 目录遍历4.2.2…

Stable Diffusion Web UI + Anaconda环境 + 本地Windows系统部署

Stable Diffusion Web UI Anaconda环境 本地Windows系统部署 最近的很多AIGC模型层出不穷,Stable Diffusion 模型作为一个开源的热门生成式模型,或许对未来的各行各业都能产生深远的影响,了解这个模型并会使用可能是很多人目前想要学习的&…

车载Mini LED持续升温,各家厂商进展如何?

去年,Mini LED背光技术在车载显示赛道上初露头角,多款搭载 Mini LED 屏幕的汽车陆续发布。随着新能源车渗透率的提高,车载显示成为明确增长的赛道,为Mini LED背光进入车载带来利好。 结合今年各家厂商披露的信息来看&#xff0c…

浮点型数据在内存的存储方式

目录 大体规则 特殊规定 由于浮点型在内存中的存储方式相较于整型的要复杂一些,而且很容易忘掉,所以就将部分知识点整理了一下,写成一篇博客。 大体规则 根据国际标准(电气和电子工程协会)IEEE 754,任意…

【数据结构】- 初识数据结构之空间复杂度(下)

文章目录前言一、空间复杂度1.1空间复杂度简解1.2常见空间复杂度的计算举例二、常见复杂度的对比总结前言 将喜欢的一切留在身边 这便是努力的意义. 本章是关于初识数据结构之空间复杂度(下) 提示:以下是本篇文章正文内容,下面案例可供参考 一、空间复…

真的干不过,00后整顿职场已经给我卷麻了,想离职了...

在程序员职场上,什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事,我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事,可遇不可求,向他学习还来不及呢。 真正让人反感的,是技术平平&#x…

D. Li Hua and Tree(set操作)

Problem - D - Codeforces 李华有一个有n个顶点和n -1条边的树。树的根是顶点1。每个顶点i的重要性为a。将子树的大小表示为该子树中顶点的数量,将重要性表示为该子树中顶点的重要性之和。将非叶顶点的重子结点表示为具有最大子树大小的子结点。如果存在多个重子&am…

安全防御 --- 入侵检测 --- IDS、IPS

入侵检测 1、入侵检测经典理论 系统访问控制要针对三类用户 (1)合法用户 (2)伪装 --- 攻破[流程控制](超出了合法用户的行为范围) 身份仿冒(可能是最早提出不能仅依赖于身份认证,还…

STM32F4+FreeRTOS+LVGL实现嵌入式快速开发(缝合怪)

极速进行项目开发,只需要懂一款芯片架构一个操作系统一个GUI。各种部件程序全靠抄 ,成为究极缝合怪。本文用stm32f407FreeRTOSlvgl演示一些demo。 原文链接:STM32F4FreeRTOSLVGL实现快速开发(缝合怪) lvgl官方的音乐播放器demo:…

微信小程序学习笔记

一、Node.js主题 1、npm:node.js包管理工具,有超过60万个JavaScript代码包可供下载 2、Node.js:运行在服务端的JavaScript,基于Chrome JavaScript建立的一个平台,基于Google V8引擎。 3、Nodejs安装教程&#xff1a…

Redis篇之主从复制及哨兵模式

主从复制及哨兵模式 1、概念 主从复制: 是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower), 数据的复制是单向的&a…