关于“内存对齐”

理一理字节对齐的那些事 微信公众号:编程珠玑 原文地址:理一理字节对齐的那些事 前言 字节对齐是我们初学C语言就会接触到的一个概念,但是到底什么是字节对齐?对齐准则又是什么?为什么要字节对齐呢?字节对齐对我们编程有什么启示?本文将简单理一理字节对齐的那些事。 什么是字节对齐 计算机中内存大小的基本单位是字节(byte),理论上来讲,可以从任意地址访问某种基本数据类型,但是实际上,计算机并非逐字节大小读写内存,而... 阅读详情

对于大部分程序员来说,“内存对齐”对他们来说都应该是“透明的”。“内存对齐”应该是编译器的 “管辖范围”。编译器为程序中的每个“数据单元”安排在适当的位置上。但是C语言的一个特点就是太灵活,太强大,它允许你干预“内存对齐”。如果你想了解更加底层的秘密,“内存对齐”对你就不应该再透明了。
一、内存对齐的原因
大部分的参考资料都是如是说的:
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
二、对齐规则
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。
规则:
1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
3、结合1、2颗推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。
三、试验
我们通过一系列例子的详细说明来证明这个规则吧!
我试验用的编译器包括GCC 3.4.2和VC6.0的C编译器,平台为Windows XP + Sp2。
我们将用典型的struct对齐来说明。首先我们定义一个struct:
#pragma pack(n) /* n = 1, 2, 4, 8, 16 */
struct test_t {
  int a;
  char b;
  short c;
  char d;
};
#pragma pack(n)
首先我们首先确认在试验平台上的各个类型的size,经验证两个编译器的输出均为:
sizeof(char) = 1
sizeof(short) = 2
sizeof(int) = 4
我们的试验过程如下:通过#pragma pack(n)改变“对齐系数”,然后察看sizeof(struct test_t)的值。
1、1字节对齐(#pragma pack(1))
输出结果:sizeof(struct test_t) = 8 [两个编译器输出一致]
分析过程:
1) 成员数据对齐
#pragma pack(1)
struct test_t {
  int a;     /* 长度4 < 1 按1对齐;起始offset=0 0%1=0;存放位置区间[0,3] */
  char b;  /* 长度1 = 1 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */
  short c;   /* 长度2 > 1 按1对齐;起始offset=5 5%1=0;存放位置区间[5,6] */
  char d;  /* 长度1 = 1 按1对齐;起始offset=7 7%1=0;存放位置区间[7] */
};
#pragma pack()
成员总大小=8
2) 整体对齐
整体对齐系数 = min((max(int,short,char), 1) = 1
整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 8    /* 8%1=0 */ [注1]
2、2字节对齐(#pragma pack(2))
输出结果:sizeof(struct test_t) = 10 [两个编译器输出一致]
分析过程:
1) 成员数据对齐
#pragma pack(2)
struct test_t {
  int a;    /* 长度4 > 2 按2对齐;起始offset=0 0%2=0;存放位置区间[0,3] */
  char b;  /* 长度1 < 2 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */
  short c;   /* 长度2 = 2 按2对齐;起始offset=6 6%2=0;存放位置区间[6,7] */
  char d;  /* 长度1 < 2 按1对齐;起始offset=8 8%1=0;存放位置区间[8] */
};
#pragma pack()
成员总大小=9
2) 整体对齐
整体对齐系数 = min((max(int,short,char), 2) = 2
整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 10 /* 10%2=0 */
3、4字节对齐(#pragma pack(4))
输出结果:sizeof(struct test_t) = 12 [两个编译器输出一致]
分析过程:
1) 成员数据对齐
#pragma pack(4)
struct test_t {
  int a;    /* 长度4 = 4 按4对齐;起始offset=0 0%4=0;存放位置区间[0,3] */
  char b;  /* 长度1 < 4 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */
  short c;   /* 长度2 < 4 按2对齐;起始offset=6 6%2=0;存放位置区间[6,7] */
  char d;  /* 长度1 < 4 按1对齐;起始offset=8 8%1=0;存放位置区间[8] */
};
#pragma pack()
成员总大小=9
2) 整体对齐
整体对齐系数 = min((max(int,short,char), 4) = 4
整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 12 /* 12%4=0 */
4、8字节对齐(#pragma pack(8))
输出结果:sizeof(struct test_t) = 12 [两个编译器输出一致]
分析过程:
1) 成员数据对齐
#pragma pack(8)
struct test_t {
  int a;    /* 长度4 < 8 按4对齐;起始offset=0 0%4=0;存放位置区间[0,3] */
  char b;  /* 长度1 < 8 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */
  short c;   /* 长度2 < 8 按2对齐;起始offset=6 6%2=0;存放位置区间[6,7] */
  char d;  /* 长度1 < 8 按1对齐;起始offset=8 8%1=0;存放位置区间[8] */
};
#pragma pack()
成员总大小=9
2) 整体对齐
整体对齐系数 = min((max(int,short,char), 8) = 4
整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 12    /* 12%4=0 */

5、16字节对齐(#pragma pack(16))
输出结果:sizeof(struct test_t) = 12 [两个编译器输出一致]
分析过程:
1) 成员数据对齐
#pragma pack(16)
struct test_t {
  int a;    /* 长度4 < 16 按4对齐;起始offset=0 0%4=0;存放位置区间[0,3] */
  char b;  /* 长度1 < 16 按1对齐;起始offset=4 4%1=0;存放位置区间[4] */
  short c;   /* 长度2 < 16 按2对齐;起始offset=6 6%2=0;存放位置区间[6,7] */
  char d;  /* 长度1 < 16 按1对齐;起始offset=8 8%1=0;存放位置区间[8] */
};
#pragma pack()
成员总大小=9
2) 整体对齐
整体对齐系数 = min((max(int,short,char), 16) = 4
整体大小(size)=$(成员总大小) 按 $(整体对齐系数) 圆整 = 12 /* 12%4=0 */
四、结论
8字节和16字节对齐试验证明了“规则”的第3点:“当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果”。另外内存对齐是个很复杂的东西,上面所说的在有些时候也可能不正确。呵呵^_^
[注1]
什么是“圆整”?
举例说明:如上面的8字节对齐中的“整体对齐”,整体大小=9 按 4 圆整 = 12
圆整的过程:从9开始每次加一,看是否能被4整除,这里9,10,11均不能被4整除,到12时可以,则圆整结束。
  

字节对齐机制 阅读详情

相关推荐

C语言字节对齐介绍

C语言字节对齐介绍 我们常提到的1字节、4字节对齐等具体是什么意思? 回答:对齐指存放当前数据的地址能否被n整除(n就是对齐值,如1,4等)。比如:地址0x0004中存放int型数据。那么它满足4字节和1字节的对齐。但地址0x0003中存放int型数据,它只满足1字节对齐,不满足4字节对齐。 我们先谈谈为什么会有字节对齐这个概念? 回答:我们应该都听过8位、16位、32位、64位等位数的处理器。如我们最常见的STM32就是32位单片机。我们所说的n位其实指的就是地址总线的宽度,与其相关的还有数据总

guoweilkd的博客 1358

字节对齐详解

字节对齐简介 1. 基本原则 任何K字节的基本对象的地址必须是K的倍数。 基本对象:int、double、long、short等基本数据类型,不包括struct、union、class。 2. 结构体的字节对齐 一个结构体,首地址必须是结构体中最大基本元素长度的整数倍。 例如: struct S1 { int i; char c; int j; }; 设S1的首地址为xp,对于S1来说,最大的基本元素为int,所以**xp**必须是4的整数倍,称S1满足4字节对齐。 解释: 回顾字节对

obvious__的博客 8721

transformer优化(一)-UNeXt 学习笔记

​它在早期阶段使用卷积,在潜在空间阶段使用 MLP。通过一个标记化的 MLP 块来标记和投影卷积特征,并使用 MLP 对表示进行建模。 ​

PLANTTHESON的博客 2033

什么是字节对齐?字节对齐与位域的计算

看的晕晕的,整理下来吧

TinyHorse的博客 6792

Win11下WSL2安装Ubuntu22.04避坑指南:从镜像源到C++环境配置

本文提供了一份详细的Win11下WSL2安装Ubuntu22.04的实战避坑指南。内容涵盖从WSL2核心安装、自定义安装路径,到更换国内镜像源以解决更新缓慢问题,并一站式配置完整的C++开发环境(包括GCC、CMake、vcpkg等),最后分享提升开发体验的进阶技巧,助你在Windows上打造高效的Linux开发工作站。

weixin_29260291的博客 562

工业金属表面缺陷检测:4种光学成像方案(明/暗/漫/背光)选型与实测对比

本文深入探讨工业金属表面缺陷检测中的4种光学成像方案(明/暗/漫/背光),详细解析其物理原理、适用场景及实测效果。通过对比不同照明方案在铝合金轮毂、不锈钢餐具等实际工业场景中的表现,提供科学的选型决策树,帮助提升缺陷检出率至99%以上,为计算机视觉在工业质检领域的应用提供实用指南。

weixin_33624741的博客 388

「iOS」————内存对齐

本文对标签指针和内存对齐算法进行了简单的学习

2301_80253909的博客 900

ensp企业网综合实验(课程设计)

使用MSTP+VRRP技术实现负载均衡以及增加网络的可靠性;出口配置napt;所有用户均为自动获取IP地址;

qq_50829760的博客 1万+

【深度C++】之“内存对齐”

我们在获得C++自定义的类或者结构体的大小时,得到的数值通常不是所有数据成员直接相加的结果,你知道这是为什么吗?

不能自拔 965

跟着团子学SAP PS:项目计划成本与项目预算设计思路

​在做SAP PS模块概览培训的时候,很多时候都会用到下面的一页PPT片子讲到项目计划成本与预算的关系,但真正这幅片子想表达的具体内容甚至大部分PS顾问也是无法阐明清楚的。 而SAP PS的设计其实是在丰富的项目管理学的基础上而开展的,所以今天从业务上结合SAP中的功能点讲一下项目成本计划及预算的逻辑。 在项目管理的十大知识领域中,项目成本管理主要是包括为使项目在批准的预算内完成而对成本进行规划...

Lucas1211的博客 3万+

Fluent 中多相流模型全面解析

3.颗粒或液滴在连续相中的运动:若关注颗粒或液滴在连续相中的运动轨迹、分布规律以及与连续相的相互作用,如喷雾干燥、气力输送等过程,Eulerian-Lagrangian 模型则是最佳选择。Eulerian-Eulerian 模型可以准确模拟气体在固体颗粒中的流动情况,包括颗粒的流化状态、气体与颗粒之间的传热传质过程,为气固流化床的优化设计和操作提供依据。通过该模型,可以了解混合器内不同位置的混合程度、颗粒的运动轨迹以及液固相间的相互作用,从而改进混合器的结构和操作条件,提高混合效率。

khhdp的博客 3086

结构体「内存对齐」

本文结合四个实例详细介绍如何计算结构体的「内存对齐」

三十的博客 484

基于AI大模型实现自然语言转SQL、SQL解释、SQL优化和SQL转换

随着大数据和人工智能技术的发展,数据分析和数据挖掘在各行各业中的应用越来越广泛。SQL(Structured Query Language)作为关系数据库的查询语言,是数据分析的重要工具。然而,SQL语言的复杂性和专业性使得许多非技术背景的用户难以直接使用,阻碍了数据的广泛利用。为了降低SQL的使用门槛,许多研究者和企业开始探索如何通过自然语言处理(NLP)技术,将自然语言转化为SQL查询语句,从而让用户可以通过自然语言与数据库进行交互。

AI天才研究院 2238

【C++】结构体中的“内存对齐“现象

内存对齐概念辨析、内存对齐规则、​底层逻辑缘由探究、(1)计算机读取规则的限制:、(2)计算机硬件层的限制:、①处理器特性、②内存构造与并行访问、③缓存一致性、④硬件平台限制、⑤内存碎片减少与空间优化

寒雒的博客 1658

27、自闭症儿童治疗与玩具设计研究

本研究探讨了自闭症儿童的治疗方法与玩具设计之间的关联,分析了游戏疗法、音乐疗法和职业疗法等在治疗中的应用,并介绍了多种针对自闭症儿童的治疗玩具案例。通过用户研究和多学科合作,提出了以Pro-Ability为核心的设计理念,开发了结合音乐疗法和精细运动训练的智能玩具套件。研究总结了当前成果与局限性,并展望了未来发展方向,旨在为自闭症儿童提供更有效的康复支持。

keras9composer的博客 210

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

简明深入地理解“内存对齐”问题

原文地址  问题一:为什么32位CPU只能读取字长(4字节)倍数的地址 答:因为32位计算机的存储系统通常使用4组存储体,存储一个字长(4字节)数据时采用分体存储方式,即4个存储体各存储1个字节,且低二位(A0和 A1)地址线未用作选址,因而CPU在寻址时只能寻到以字长(4字节)为倍数的地址。同理,16位计算机系统普遍采用两组存储体(奇/偶)分体存储数据, 且低一位(A0)地址线未用作选址,从

Leo____Wang的博客 606

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

“内存对齐“和“cache line“伪共享的个人理解

先上一张图,如有侵权麻烦告知;这张图描述了不同存储介质的存取速度: 寄存器>>cache(l1/l2/l3)>>ram>>flash>>硬盘>>网络存储. 由于cpu的速度要远快于存储介质的读写速度,且存在不同类型的存储介质,受他们的体积,成本,效率等因素的影响,产生了我们今天用到的计算机的存储结构. 内存对齐 前言 我们一直会听到"内存对齐"这一名词,但是不清楚为什么内存需要对齐.好像就是一个默认的定理,只管拿来用,确不懂该如何证明..

steveliu->blog 1868

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

“内存对齐“相关面试题解答

(1)大小端决定了多字节数据(如整数)在内存中的存储顺序。你可以把内存地址想象成从左(低地址)到右(高地址)的格子。小端模式像“倒着放”:数据的低位字节(如个位)存在左边的低地址,高位字节存在右边。大端模式则像“正着放”:数据的高位字节(如百位)存在左边,更符合我们书写数字的习惯。(2) 使用联合体int main()unionint i;} test;// 设置一个int值{ // 检查低地址处的字节是否是最高位字节{ // 检查低地址处的字节是否是最低位字节else。

dingdianduoyu_的博客 903

C语言中“内存对齐”解析

C语言字节对齐 转载连接1:http://blog.youkuaiyun.com/21aspnet/article/details/6729724 转载连接2:http://blog.chinaunix.net/uid-10995602-id-2918694.html 文章最后本人做了一幅图,一看就明白了,这个问题网上讲的不少,但是都没有把问题说透。 一、概念      ...

weixin_30858241的博客 260

内存对齐:你写的每行代码,都在为这隐藏的“内存漏洞”付费

内存对齐是计算机系统组织数据在内存中存放位置的一种规则。简单来说,它要求特定类型的数据必须存放在内存地址为某个数值倍数的位置上。举个例子:一个4字节的整数,可能被要求存放在地址为4的倍数的位置上(如0、4、8、12等),而不能存放在地址2或6这样的位置。这种看似“浪费”空间的安排,背后有着深刻的硬件原因。使用普通malloc分配的内存,无法满足超过基本对齐的要求。需要使用平台提供的对齐分配函数,或自行实现对齐逻辑。内存对齐是连接软件与硬件的桥梁之一。

qq_32775541的博客 209

C语言内存精讲系列(十):虚拟内存、C 语言的 “假地址” 与内存对齐

虚拟内存是中间层:C 语言打印的地址是虚拟地址,需通过 CPU 映射到物理地址,解决了 “地址冲突” 问题;虚拟地址的优势:隔离不同程序的地址空间(安全),提高内存使用效率(高效);内存对齐:CPU 按步长读内存,编译器通过对齐让数据不跨块,提高寻址效率,代价是少量空间浪费。这些底层机制虽然不直接写代码,但理解它们能帮你解决很多 “奇怪” 的问题(比如结构体大小、指针越界),也是后续学习操作系统、嵌入式开发的基础。课后大家可以自己改改代码,比如把全局变量改成局部变量,看看地址会不会变;

xingke的专栏 755

关于“内存对齐”最通俗易懂的解释

关于“内存对齐”最通俗易懂的解释。

weixin_40506939的博客 373

【“内存对齐“在计算结构体大小时的影响】

有关结构体的声明、初始化不同写法与区别的相关知识,以及结构体内存对齐在使用sizeof计算大小时的影响,分析内存对齐的意义和原因

qq_62407309的博客 458

“内存对齐(只针对于自定义数据类型,基本数据类型无内存对齐概念)”详解

内存对齐(只针对于自定义数据类型,基本数据类型无内存对齐概念) 为什么要内存对齐? ① 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 ② 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。 C语言和C++语言中空结构体所占的空间 在C++中规定了空结构体和空类的内存所占大小为1字节,因为c++中规定,任何

超级霸霸强的博客 407

【C语言进阶】结构体全解:从“内存对齐”到“位段”的底层秘密

本文系统总结了C语言结构体的核心知识点与常见陷阱。首先分析了结构体声明中的两大坑点:匿名结构体的类型不兼容问题和自引用结构体的正确实现方式。然后深入讲解了内存对齐机制,包括其原理、四大对齐规则以及通过成员排序优化内存占用的实战技巧。接着介绍了位段这一高级特性及其使用限制,强调不能对位段成员取地址。最后给出结构体传参的最佳实践,建议优先使用指针传参以避免性能损耗。全文通过具体代码示例,帮助读者掌握结构体的内存布局特性,提升对C语言底层机制的理解。

2402_86760180的博客 707

缓存友好编程:从结构体对齐到数据布局的“内存效率革命”

文章摘要:CPU缓存优化是提升程序性能的关键因素。通过调整结构体成员顺序减少内存填充,可以显著提高缓存命中率。测试显示优化后的结构体访问时间减少66%,性能提升200%。核心技巧包括按对齐要求排列成员、同类型成员集中存放、使用alignas指定对齐等。缓存友好编程的本质是减少主存访问,让数据尽可能留在高速缓存中,这种数据布局优化往往比算法优化带来更显著的性能提升。

huahua8088的博客 795
下一篇: Effective STL: Item 44:优先使用与泛型算法同名的成员函数
AlwaysSLH
博客等级 码龄20年 63粉丝 17原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值