关于内存对齐的全面详细解释

C/C++中结构体内存对齐(边界对齐),#pragma pack设置 一、首先,为什么要进行内存对齐,即在内存中为什么要这么存放数据呢??? 原因一:在内存中存放数据是为了给CPU使用,但是CPU从内存中读取数据并非是一个字节一个字节进行读取的,而是一块一块进行读取的,块的大小(具体和数据总线宽度等有关)称为内存读取粒度(memory granularity)。例如:CPU一次从内存读取8字节,而当一个int(4字节)存储在如下位置时,CPU如何获取该int值呢?... 阅读详情

一、内存对齐的原因
1、平台原因(移植原因):内存对齐其实不是操作系统内存架构范畴的问题,而是CPU架构方面的问题。不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。x86和x64系统支持自动内存对齐,IA-64系统则不能访问未对齐的内存地址。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

二、对齐规则
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16...8192来改变这一系数,其中的n就是你要指定的“对齐系数”。关键字__declspec(align(n)),n=1,2,4,8,16...8192也能改变具体变量的对齐方式。

可以这样理解:
1、__declspec(align(n))和#pragma pack(n)是一对兄弟,前者规定了对齐系数的最小值,后者规定了对齐系数的最大值。
2、当两者同时出现时,前者拥有更高的优先级。即,当两者同时出现且值矛盾时,后者将不起作用。
3、当变量size大于等于#pragma pack(n)指定的n,而且__declspec(align(n))指定的数值n比对应类型长度小的时候,这个__declspec(align(n))指定将不起作用。
4、当#pragma pack(n)指定的值n大于等于所有数据成员size的时候,这个值n将不起作用。


简单数据成员对齐规则:
对齐系数 = max(__declspec(align(n))指定的n,min(自身size,#pragma pack(m)指定的m))。
结构型数据成员对齐规则:
对齐系数 = max(__declspec(align(n))指定的n,min(max(所有简单数据成员的size,包括嵌套),#pragma pack(m)指定的m))。
结构整体对齐规则:
对齐系数 = max(max(修饰该结构或修饰该结构成员的所有__declspec(align(n))指定的n,包括嵌套),min(max(所有简单数据成员的size,包括嵌套),#pragma pack(m)指定的m))。

上述规则看似很复杂,其实可总结为:
    对于成员对齐,第一个数据成员始终放在偏移为0的地方,在没有被__declspec(align(n))修饰时,以后每个数据成员的对齐,按照#pragma pack(n)指定的数值n和这个数据成员自身size中,比较小的那个进行;当被__declspec(align(n))修饰时,再使上述结果与__declspec(align(n))指定的n进行比较,然后按较大的那个进行。如果成员本身又是结构,则找到该结构中所有简单成员的size最大值,然后与#pragma pack(n)指定的数值n进行比较,取较小的那个;如果该结构成员本身被__declspec(align(n))修饰,再使上述结果与__declspec(align(n))指定的n进行比较,然后按较大的那个进行。
    对于结构整体的对齐,取结构中所有简单成员的size的最大值(如果有结构型成员,则将其展开,取其中的简单数据成员),然后与#pragma pack(n)指定的数值n进行比较,取较小者;如果结构或结构成员(包括嵌套)被__declspec(align(n))修饰,则取所有__declspec(align(n))(包括嵌套)指定的n的最大值,然后与上述得到的较小者进行比较,取其中的较大者。

三、试验
我们通过一系列例子的详细说明来证明这个规则吧!

我们首先确认在试验平台上的各个类型的size,以及默认对齐系数:
sizeof(char) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(double) = 8

#pragma pack(show) = 8 (以警告的方式显示编译器当前的默认对齐系数)


例1:
1)成员数据对齐:
#pragma pack(1)
struct Str{
char a; /* 起始offset=0;存放位置区间[0] */
short b; /* min(2,1)=1 按1对齐;起始offset=1 1%1=0;存放位置区间[1,2] */
__declspec(align(8)) int c; /* max(8,min(4,1)) 按8对齐;起始offset=3 3%8=!0;直到增加为8 8%8=0;存放位置区间[8...11] */
double d; /* min(8,1)=1 按1对齐;起始offset=12 12%1=0;存放位置区间[12...19] */
char e; /* min(1,1)=1 按1对齐;起始offset=20 20%1=0;存放位置区间[20] */
};
成员总偏移量 = 21
2)整体对齐
整体对齐系数 = max(max(8),min(max(1,2,4,8,1),1)) = 8
21%8!=0;直到增加为24 24%8=0;所以整体的size = 24

例2:
1)成员数据对齐:
#pragma pack(16)
struct Str{
char a; /* 起始offset=0;存放位置区间[0] */
short b; /* min(2,16)=2 按2对齐;起始offset=1 1%2=!0;直到增加为2 2%2=0;存放位置区间[2,3] */
__declspec(align(2)) double c; /* max(2,min(8,16)) 按8对齐;起始offset=4 4%8=!0;直到增加为8 8%8=0;存放位置区间[8...15] */
int d; /* min(4,16)=4 按4对齐;起始offset=16 16%4=0;存放位置区间[16...19] */
};
成员总偏移量 = 20
2)整体对齐
整体对齐系数 = max(max(2),min(max(1,2,8,4),16)) = 8
20%8!=0;直到增加为24 24%8=0;所以整体的size = 24

例3:
1)成员数据对齐:
struct Str{
__declspec(align(16)) char a; /* 起始offset=0;存放位置区间[0] */
short b; /* min(2,8)=2 按2对齐;起始offset=1 1%2=!0;直到增加为2 2%2=0;存放位置区间[2,3] */
__declspec(align(2)) double c; /* max(2,min(8,8)) 按8对齐;起始offset=4 4%8=!0;直到增加为8 8%8=0;存放位置区间[8...15] */
int d; /* min(4,8)=4 按4对齐;起始offset=16 16%4=0;存放位置区间[16...19] */
};
成员总偏移量 = 20
2)整体对齐
整体对齐系数 = max(max(16,2),min(max(1,2,8,4),8)) = 16
20%16!=0;直到增加为32 32%16=0;所以整体的size = 32

例4:
1)成员数据对齐:
#pragma pack(1)
struct Str{
char a; /* 起始offset=0;存放位置区间[0] */
__declspec(align(2)) short b; /* max(2,min(2,1)) 按2对齐;起始offset=1 1%2=!0;直到增加为2 2%2=0;存放位置区间[2,3] */
};
struct Str总偏移量 = 4,按max(max(2),min(max(1,2),1))进行整体对齐后,其size为4。

struct Str2{
char a; /* 起始offset=0;存放位置区间[0] */
struct Str b; /* min(max(1,1,2),1) 按1对齐;起始offset=1 1%1=0;存放位置区间[1...4] */
};

struct Str2总偏移量 = 5
2)整体对齐
整体对齐系数 = max(max(2),min(max(1,1,2),1)) = 2
5%2!=0;直到增加为6 6%2=0;所以整体的size = 6

简单数据成员对齐规则:
对齐系数 = max(__declspec(align(n))指定的n,min(自身size,#pragma pack(m)指定的m))。
结构型数据成员对齐规则:
对齐系数 = max(__declspec(align(n))指定的n,min(max(所有简单数据成员的size,包括嵌套),#pragma pack(m)指定的m))。
结构整体对齐规则:
对齐系数 = max(max(修饰该结构或修饰该结构成员的所有__declspec(align(n))指定的n,包括嵌套),min(max(所有简单数据成员的size,包括嵌套),#pragma pack(m)指定的m))。

例5:
1)成员数据对齐:
struct Str{
char a; /* 起始offset=0;存放位置区间[0] */
__declspec(align(16)) short b; /* max(16,min(2,8)) 按16对齐;起始offset=1 1%16=!0;直到增加为16 16%16=0;存放位置区间[16,17] */
};
struct Str总偏移量 = 18,按max(max(16),min(max(1,2),8))进行整体对齐后,其size为32。

struct Str2{
int a; /* 起始offset=0;存放位置区间[0...3] */
__declspec(align(8)) struct Str b; /* max(8,min(max(1,2),8)) 按8对齐;起始offset=4 4%8=!0;直到增加为8 8%8=0;存放位置区间[8...39] */
double c; /* min(8,8)=8 按8对齐;起始offset=40 40%8=0;存放位置区间[40...47] */
char d; /* min(1,8)=1 按1对齐;起始offset=48 48%1=0;存放位置区间[48] */
};

struct Str2总偏移量 = 49
2)整体对齐
整体对齐系数 = max(max(8,16),min(max(4,1,2,8,1),1)) = 16
49%16!=0;直到增加为64 64%16=0;所以整体的size = 64

为什么要内存对齐? 为什么会有内存对齐? 平台原因: 不是所有的硬件平台都能访问任意内存地址上的数据,某些平台只能在一些地址处获取特定类型的数据,否则抛出硬件异常。为了使同一个程序可以在多平台运行,需要进行内存对齐。 硬件原因: ... 阅读详情

相关推荐

张正友标定法_单目-线激光三维扫描系统中光刀平面的标定

单目-线激光三维扫描系统中光刀平面的标定线结构光有结构简单、精度高、测速快等特点,被广泛应用于三维重建领域。线结构光三维扫描系统由一个相机和一个线结构光投射器构成,线结构光投射器将线结构光投射到被测物体表面,相机采集带有线激光的被测物体图像,根据相机和线激光投射器间的相对位置关系,使用激光三角法计算出激光线上的点在相机坐标系下的坐标。激光三角法原理如下图所示,线激光投射的扇形区域可以看作是一个平面...

weixin_39616379的博客 1074

为什么要进行内存对齐?本文也许可以帮到你

为什么存在内存对齐? 大部分的参考资料都是如是说的: 1. 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址 处取某些特定类型的数据,否则抛出硬件异常。 2. 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理 器需要作两次内存访问;而对齐的内存访问仅需要一次访问。 总体来说: 结构体的内存对齐是拿空间来换取时间的做法。 但是关于上面的说法,其实是很难理解的,但是相信上面也是大家搜到的最多的答

学无止境 742

驱动钛丝(SMA)的应用(5)汽车腰托气阀常见问题及解决方案

财哥在前段时间发布的《驱动钛丝(SMA)的应用(1)汽车腰托支撑按摩气阀模块》一文,引发了很多企业的拜访和交流。 目前很多厂家已经启动或正在进行相关研发,同时也遇到了诸如:钛丝选型、驱动位移、响应设计、温度控制、力量设计、点动滞后、铆接工艺、量化生产等问题。

weixin_39168671的博客 1241

【内存】内存对齐 的原理

目录 内存对齐的原因 内存对齐的原理 内存对齐的原因 1.平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 2.性能原因: 内存对齐最最底层的原因是内存的IO是以64bit为单位进行的,因此内存对齐为了高效的内存IO,大部分都是更为高效的高速缓存IO。 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。你i.

我的笔记本 2450

AF3 ProteinDataset类的_patch方法解读

AlphaFold3 protein_dataset模块 ProteinDataset 类  _patch 方法的主要目的是围绕锚点残基(anchor residues)裁剪蛋白质数据,提取一个局部补丁(patch)作为模型输入。

qq_27390023的博客 1148

ESP32开发环境与微信小程序通信的完整示例

通过搭建稳定的esp32开发环境,实现其与微信小程序间的双向通信,涵盖Wi-Fi连接、数据收发与协议设计,为物联网应用提供低成本解决方案。

weixin_42126677的博客 1132

LCD DRM驱动框架分析二

本文是基于rk3566 / rk3568平台从LCD代码层面上对LCD DRM框架进行分析。 一、uboot阶段 1、涉及的驱动文件 2、uboot代码流程分析 2.1)各probe函数的加载 2.1.1)各bind函数是在设备和驱动匹配时(uboot启动阶段)加载的。 2.1.2)各probe函数是在rockchip_display_probe中解析设备树时,通过uclass_get_device_by_xxx(uclass_get_device_by_ofnode/uclass_get.

qq_33782617的博客 5565

Vivado ILA抓不到低频信号?试试Capture Control模式,保姆级配置教程(附PWM调试实例)

本文详细解析了Vivado ILA的Capture Control模式在低频信号捕获中的应用,特别针对PWM调试等场景提供保姆级配置教程。通过条件采样和时间拉伸技术,有效解决传统ILA采样在低频信号调试中的存储深度不足、关键信号丢失等问题,并附赠呼吸灯PWM的完整调试实例,帮助FPGA开发者提升调试效率。

weixin_42549451的博客 350

为什么要进行内存对齐?

关于内存对齐的博客,网上可以搜到很多,但是大多讲述的都是关于内存对齐的规则,所以本篇文章就不再继续介绍了,而至于为什么要进行内存对齐,如果细心的网友有进行过大量的搜索一定会发现,下面这段话是大家经常见到的: 1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。 2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,对于访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

学无止境 2766

硬件工程师笔记——电子器件汇总大全

本文系统总结了14种常用电子器件的工作原理及功能应用,包括电阻、压敏电阻、电容、电感、二极管、三极管、MOS管、晶振、光耦、IGBT、继电器、磁珠、可控硅和线性稳压器。每种器件从结构原理、工作特性到典型应用进行全面解析,如电阻的限流分压、电容的储能滤波、三极管的放大开关等。重点阐述了各器件在电路设计中的关键作用,如IGBT的功率控制、继电器的隔离保护、LDO的电压稳定等,并提供了实际电路应用案例。文章还整理了硬件工程师笔试面试相关的知识点和真题资源,为电子工程师提供全面的技术参考。

XU157303764的博客 2万+

【新能源汽车DCDC变换器测试优化全攻略:解决电能质量/发热/过充等核心痛点】

高压直流转12V低压的DCDC变换器是新能源汽车电源系统的核心枢纽,承担着为整车低压附件、控制器及12V蓄电池供电/补电的关键作用。在新能源汽车乘用车、商用车等不同车型实际运营中,因PDU内DC/AC等模块干扰、DCDC自身设计缺陷、整车匹配性不佳及测试验证不充分,频发12V输出电能质量差导致后端元器件烧毁、变换器发热严重、蓄电池过充/欠充、智能补电功能失效等问题,还伴随低压侧电压瞬跌/浪涌、电磁干扰超标、振动后接触不良、高温下效率骤降等行业高频故障,直接影响整车可靠性和运营安全性。本文基于国标。

优快云-新能源汽车研发测试专业博主 1267

关于内存对齐详细解释

什么是内存对齐? 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自的空间相加,这里涉及到内存对齐的问题。访问未对齐的内存,处理器需要访问两次(数据先读高位再读低位然后进行拼接),而访问对齐的内存,只需要一次。为了提高效率,所以进行内存对齐。windows的默认对齐数是8,linux中默认对齐数为4. 为什么会产生内存对齐的原因? 1.平台原因: 某些...

suoyudong的博客 1145

Untiy之如何实现AI+MR (Pico4u 相机推流MR画面给Server做实时AI图像识别)

本文介绍了基于Pico4U企业版开发AI+MR应用的实现方案。文章详细说明了硬件准备步骤,包括购买企业版设备、申请相机权限和注册管理平台。重点讲解了Unity开发中获取摄像头画面的两种技术方案:通过Overlay直接渲染到Android Surface,或使用API获取图像数据转换为Texture。提供了完整的代码示例和权限配置说明,并揭示了底层通过JNI调用Android原生API的技术原理。该方案适用于带电操作等实习场景,可提升安全性和学习趣味性。

TxNet 1342

KaihongOS落地实战:架构、开发、编译与排查全解析

操作系统是连接硬件与应用生态的桥梁,多内核抽象与分布式协同正成为新型系统设计的核心。KaihongOS 通过内核抽象层与分布式软总线,将设备能力资源化,让应用无需感知物理拓扑即可跨端调用,真正实现一次开发、多端部署。其构建系统与工具链支撑从源码到镜像的完整流程,设备烧录与日志调试则保障交付效率。实际落地中,处理好设备发现、时钟同步与权限管控等隐性坑,结合UI渲染与内存的性能调优,是团队从Demo走向规模交付的关键。本文以工程视角拆解KaihongOS的架构原理与实战经验,为多设备场景下的开发与适配提供参考。

weixin_34269583的博客 357

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

内存对齐详细解释

内存对齐详细解释 如果结构体存储下标从0開始的 先是依照#pragma pack(8)參数依次和数据成员比較:依照成员下标是比較结果中小者的倍数; 最后再依照#pragma pack(8)參数与结构体成员占空间最大者比較,结构体总体的长度是比較结果中小者的倍数;   1、分析说明: 字节对齐(#pragma pack(2)) 输出结果:sizeof(structtest_t)...

weixin_33756418的博客 124

计算机控制技术及应用

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

posix_memalign详细解释(转)——自定义对齐大小的内存分配函数

转载:http://hi.baidu.com/freelonely/blog/item/340341077c4d287302088189.html 预对齐内存的分配 在大多数情况下,编译器和C库透明地帮你处理对齐问题。POSIX 标明了通过malloc( ),calloc( ), 和realloc( )返回的地址对于任何的C类型来说都是对齐的。在Linux中,这些函数返回的地址在32位系...

weixin_30485799的博客 251

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

内存对齐、内存对齐规则解释、内存对齐原理

一、内存对齐的原因 我们都知道计算机是以字节(Byte)为单位划分的,理论上来说CPU是可以访问任一编号的字节数据的,我们又知道CPU的寻址其实是通过地址总线来访问内存的,CPU又分为32位和64位,在32位的CPU一次可以处理4个字节(Byte)的数据,那么CPU实际寻址的步长就是4个字节,也就是只对编号是4的倍数的内存地址进行寻址。同理64位的CPU的寻址步长是8字节,只对编号是8的倍数的内存...

草帽~小子^的博客 7393

什么是内存对齐

内存对齐

qq_42376419的博客 1535

结构体内存对齐

本文简要介绍了c/c++中内存对齐,总体来说和边界对齐类似,并对其使用的原因做出了简单的介绍

黎鹤舞828的博客 1731

什么是内存对齐?为什么要内存对齐?

要了解为什么要内存对齐,首先我们要了解什么是内存对齐 什么是内存对齐 关于什么是内存对齐,我们先来看几个例子 typedef struct { int a; double b; short c; }A; typedef struct { int a; short b; double c; }B; 分别对他们求大小,sizeof(A)...

zw_ss 4万+

[C++] 内存对齐的目的和原则是什么?如何调整内存对齐的值

为什么需要内存对齐? 内存对齐(memory alignment).为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。也就是说“内存对齐”应该是编译器的管辖范围,非常依赖平台. 全局关闭内存对齐 先来看下面的结构体: struct test{ int a; int b; char c; }A; 1 添加预处理指令 #pragma pack(1) #paragma pac

小x的博客 4229

linux内存对齐

一,内存地址对齐的概念    计算机内存中排列、访问数据的一种方式,包含基本数据对齐和结构体数据对齐。    32位系统中,数据总线宽度为32,每次能够读取4字节数据。地址总线为32,最大寻址空间为4GB。但是由于最低位A[0]~A[1]是不用于寻址的,因此只能访问4的倍数的地址空间,但是寻址空间还是2^30*字长=4GB。   因此内存中除了结构体中成员变量之外的基本类型的开始

逐波与逆流 2784

C 内存对齐

C 内存对齐 对于程序员来说,最烦恼最耗时的工作莫过于与内存打交道,但是内存至关重要,不得不对其保持最大的警惕。 为什么需要内存对齐? 平台原因:不是所有的一欧诺个见平台都能访问任意地址上的任意数据的;某些硬件平台如果访问未对齐的地址,则会报出对齐错误,有些专业的处理器通常不支持访问未对齐地址。 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界对其。原因在于,为了访问未对齐的内存,...

hao555sky 262
上一篇: 大端,小端
下一篇: DC保存至BMP图像
desow
博客等级 码龄17年 36粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值