C++ 结构体内存对齐

C++ 结构体对齐详解 在C++中,结构体(struct)的对齐是指编译器为确保结构体成员在内存中的地址满足特定的对齐要求而进行的调整。对齐有助于提高访问速度,但同时也可能导致内存空间的浪费。默认对齐:通常情况下,最好使用编译器的默认对齐方式,以获得最佳性能。手动对齐:只有在明确知道需要节省内存,并且能接受性能损失的情况下才使用手动对齐。理解和控制结构体的对齐对于编写高效、可靠的C++程序非常重要。希望这篇详解能够帮助你更好地掌握结构体对齐的概念和应用。 阅读详情

刚出学校那会,出去找实习工作,面试答题被问到结构体内存大小的问题,虽然自己以前接触过,但是也还是答错了,最终面试的这份工作黄了。一年后的最近,还是在找工作的路上,面试了一家游戏公司,其中也是答题环节有一道题被问到结构体的内存大小,也还是答错了,最后面试也还是黄了。

到了现在自己才醒悟过来,这些知识点是有多么的重要,所以咬紧牙,把这个内容的知识点啃下来,写下这篇博客记录下来!


先看一段简单的程序

#include <iostream>

using namespace std;

typedef struct A {
	char c;
	int i;
};

typedef struct B {
	char c;
	int i;
	double d;
};

typedef struct C {
	char c;
	int i;
	double d;
	char c1;
};

int main(void) {

	cout << "struct A size = " << sizeof(struct A) << endl;
	cout << "struct B size = " << sizeof(struct B) << endl;
	cout << "struct C size = " << sizeof(struct C) << endl;

	return 0;
}

如果不运行,那么大家知道结构体A、B、C所占用的内存大小是多少吗?

运行截图:
在这里插入图片描述

以上输出的结果并非实际成员占用的字节数,这就是结构体的内存对齐!

按照我们正常的逻辑,结构体A的内存大小应该是5个字节,结构体B的内存大小应该是13个字节,结构体C的内存大小应该是14字节才对!
但是为什么是8、16和24呢?将在下面进行讲解。

结构体内存对齐原因

  1. 平台原因(移植原因):
    “不是所有的硬件平台都能访问任意地址上的任意数据;某些硬件平台只能在某些特定地址处取某些特定的数据,否则就会抛出硬件异常”。也就是说在计算机在内存读取数据时,只能在规定的地址处读数据,而不是内存中任意地址都是可以读取的。

  2. 效率原因:
    正是由于只能在特定的地址处读取数据,所以在访问一些数据时,对于访问未对齐的内存,处理器需要进行两次访问;而对于对齐的内存,只需要访问一次就可以。 其实这是一种以空间换时间的做法,但这种做法是值得的。

结构体对齐规则

  1. 第一个成员在结构体变量偏移量为0 的地址处,也就是第一个成员必须从头开始。

  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数为编译器默认的一个 对齐数与该成员大小中的较小值。vs中默认值是8 Linux默认值为4(可以通过#pragma pack (N) 修改,使用#pragma pack(show) 可以查看对齐值),但修改时N的取 值只能设置成1, 2,4,8,16.
    在这里插入图片描述

  3. 结构体总大小为最大对齐数的整数倍。(每个成员变量都有自己的对齐数)

  4. 如果嵌套结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是 所有最大对齐数(包含嵌套结构体的对齐数)的整数倍。(具体详情,请看下面代码结构体G)

结构体对齐的规则都是依据上面四条规则进行的!

结构体对齐示例

在这里插入图片描述

typedef struct A {
	char c;
	int i;
};

根据第二和第三条规则,VS中最大默认对齐数是8,结构体中最小的是int类型的4,8 < 4,所以结构体A的对齐数是4.
所以即使char类型占一个字节,但是他在内存中也会占用4个字节,来对齐4字节数,这就是所谓的,牺牲空间来换取时间!

后面的也是一样的道理!

如果是这样的结构体,那么他们的内存将会是多少呢?

typedef struct D {
	char c;
	int i;
	double d;
	char c1;
	int b;
	char c2;
};

typedef struct E {
	int i;
	double d;
	char c;
	double d2;
};

typedef struct F {
	int i;
	double d;
	char c;
	double d2;
	int i2;
	int i3;
	char c2;
	char c3;
	char c4;
	int i4;
};

typedef struct G {
	int i;
	double d;
	struct E e;
	char c;
	double d2;
};

在这里插入图片描述
下面是他们的内存关系图:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

上述四张图基本涵盖了所有情况,希望这四张图大家能看明白是怎么个回事!

我本人的理解:
以它为例,

typedef struct D {
	char c;
	int i;
	double d;
	char c1;
	int b;
	char c2;
};

首先我会先找到结构体中最大的变量字节大小(内部结构体除外),然后使用加法原则向其对齐。(结构体D的对齐数是8)
c 是1个字节,i是4个字节,c + i 等于5字节,为了符合内存对齐的原则,他俩占用最前方8个字节的内存,当然c是占4个字节,i也是占4个字节,这样4 + 4 等于8,才符合内存对齐。
d是8个字节,紧接着后面存储8个字节。
c1是一个字节,b是4个字节,计算规格和上面一样,占用8个字节。
最后剩余一个c2是一个字节,当然为了符合内存对齐的原则他在结构体中是占8个字节的。
所以最后计算出内存大小为:
(c + i) == 8(字节)
d == 8(字节)
(c1 + b) == 8(字节)
c2 == 8(字节)
8 + 8 + 8 + 8 == 32(字节)

相信再配合下图,一定可以理解是什么原理的:
在这里插入图片描述


总结
结构体内存对齐这是比较底层的知识点了,当然这也是我们程序员需要掌握的,特别是服务器开发人员。
对齐时需要注意对齐数!

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

相关推荐

C++内存对齐

这里写目录标题空类/静态成员内置类型数据成员结构体数据成员虚函数继承内存对齐的意义 内存对齐的基本原则: 结构(struct/class)的内置类型数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的起始位置要从自身大小的整数倍开始存储。 如果一个结构A里有结构体成员B,则结构体A的成员要从结构体B内部“最宽基本类型成员”的整数倍地址开始存储(如struct a里存有struct b,b里有char, int, double等元素,那b应该从8的整数倍位置开始存储)。 结构体的总大小为结

TABE_的博客 4318

C/C++结构体内存对齐

C/C++结构体内存对齐原理的详细解释,详细介绍对齐规则,并利用一些示例进行讲解

mrqiuwen的博客 2368

C++结构体-内存对齐

使用关键字 struct 。 尽管结构体可以包含成员函数,但它们很少这样做。所以,通常情况下结构体声明只会声明成员变量。 结构体声明通常不包括 public 或 private 的访问修饰符。 类成员默认情况是private 的,而结构体的成员则默认为 public。 结构体内存对齐 1.结构体为什么要进行内存对齐?怎么对齐? 内存对齐是一种典型的空间换时间以提高效率的方式。 若无内存对齐情况下,按照连续存储时,1234 5678作为8字节,在结构体中,char c会存储在1号位上,而int i

DENGXI1997的博客 772

【C/C++】内存对齐(超详细,看这一篇就够了)

下面的结论均为系统默认对齐规则下进行的: 通常情况:我总结的规律如下:结构体中间:各结构体的起始地址按照各个类型变量默认规则进行摆放,但除了 char 类型变量(详见一),char 类型变量一般遵循 2 的倍数地址开始存储。详见例2。结构体最后(重要):视结构体中最大类型是哪一个,如果是像 int 类型那样是 4 个字节的,并且结构体的结尾地址不满足 4 的倍数的话,向离最近的 4 的倍数地址补齐;如果是像 double 类型那样是 8 个字节的,并且结构体的结尾地址不满足 8 的倍数的话,向离最近的 8

涛涛子的博客 3万+

C++结构体内存对齐规则

C++结构体内存对齐规则

光阴迷客的知识库 1146

C++笔记之内存对齐、结构体对齐

如果尝试在未对齐的地址上读取数据,硬件会直接触发异常或崩溃(如总线错误 Bus Error)。CPU 并不是一个字节一个字节地从内存中读取数据的,而是以块(Chunk/Word)为单位读取,常见的块大小是 4 字节(32位系统)或 8 字节(64位系统)。简单来说,就是要求数据的起始地址必须是某个数字(通常是 2、4、8 等)的倍数。虽然从逻辑上看,内存就像一个连续的字节数组,CPU 可以访问任意位置,但现代计算机的底层硬件并不是这样工作的。在 C/C++ 等语言中,结构体(struct)的对齐最为典型。

小勇博客 478

C++ 类、结构体、内存对齐

结构体与类的核心区别在于:结构体是值类型,内存栈分配,不支持继承;而类是引用类型,堆分配,支持继承。C++中结构体成员默认public,类默认private。结构体大小计算需要考虑内存对齐,确保成员偏移量是自身大小的整数倍

平平无奇的小甜菜 1244

从零开始用QP框架开发STM32:事件驱动编程实战指南(附状态机设计技巧)

本文详细介绍了如何使用QP框架在STM32上实现事件驱动编程,包括状态机设计技巧和嵌入式开发实践。通过对比传统前后台系统和RTOS,展示了QP框架在资源占用、实时性和代码可维护性方面的优势,并提供了从环境搭建到高级状态机设计的完整指南。

h6i7j8的博客 1173

c++结构体内存对齐

本文讨论c/c++内存对齐方式与原则,图文并茂说明,还有空结构体对齐特例。

noevil的博客 1759

ADS负载牵引仿真避坑指南:从零开始搞定Loadpull模板设置

本文是一份针对ADS负载牵引仿真的深度避坑指南,详细解析了Loadpull模板从初始化配置到结果解读的全过程。文章重点阐述了如何根据设计目标灵活设置扫描圆、采样点等关键参数,以解决仿真不收敛、结果不完整等常见问题,并指导读者在功率与效率之间做出理性权衡,最终提取出用于匹配网络设计的最优负载阻抗。

weixin_29234423的博客 593

自定义LayoutManager实现android-pile-layout滑动卡片堆叠效果

这是我的第一篇博客,总算有个契机开始写博客了,就从自定义LayoutManager开始吧。 前段时间看到一个项目(android-pile-layout),效果特别不错,这是效果图: 效果确实不错,我看了下实现,是用的自定义的ViewGroup实现的,计算什么还搞的挺复杂的,具体的没细看。作者说也尝试过用LayoutManager实现,但是没找到合适的数学模型,好吧,看到数学模型我

u014296305的博客 1万+

[C++]关于结构体内存对齐

我们知道不同的变量、数组都有自己的大小,结构体也有自己的大小,但是= 该结构体成员变量自身的大小与编译器默认的一个对齐数的较小值。vs编译器中的默认对齐数是8,有些编译器没有设置默认对齐数,对齐数就是该成员变量自身的对齐数。

m0_64476561的博客 1070

Android开发必备:TBS腾讯浏览服务静态集成完整指南(附Demo下载)

本文详细解析了Android开发中TBS腾讯浏览服务的静态集成方案,通过对比动态集成,深入剖析了其核心原理与适用场景。文章提供了从环境准备、资源获取、项目配置到代码初始化的完整指南,并重点介绍了WebView与文件预览等高级特性的实战应用。针对集成过程中的常见问题,提供了详尽的排查清单与性能调优建议,旨在帮助开发者构建极致稳定、不依赖网络的WebView与文件预览功能。文末附有经过验证的Demo项目可供下载参考。

earth的博客 366

C++结构体内存对齐

结构体的大小并不是简单地将每个结构体成员的大小相加就能得到。cpu一次能读取多少内存要看数据总线是多少位,如果是16位,则一次只能读取2个字节,如果是32位,则可以读取4个字节,并且cpu不能跨内存区间访问。三个原则:1、第一个成员的首地址为0.2、每个成员的首地址是自身大小的整数倍3、结构体的总大小,为其成员中所含最大类型的整数倍。

Rainbow 485

MOS管关断时尖峰电压的5种实用抑制方案(附实测数据对比)

本文针对MOS管关断时产生的尖峰电压问题,提供了五种经过实验室实测验证的实用抑制方案。文章从尖峰电压的成因分析入手,详细阐述了优化PCB布局、设计RC缓冲电路、选用TVS二极管钳位、调节驱动电路以及使用磁珠吸收高频振荡等方法的原理、实施步骤与实测数据对比,为硬件工程师解决开关电源和电机驱动中的过压应力与EMI问题提供了系统性的实战指南。

1235

华为MetaERP月结加速方案:并行关账技术深度解析

【摘要】华为MetaERP并行关账技术通过创新架构设计,将传统串行月结流程(8-12小时)优化为并行执行(2-4小时)。关键技术包括:1)基于DAG引擎的任务依赖分析,实现模块/子任务三级并行;2)Saga模式分布式事务保障数据一致性;3)动态资源分配算法提升CPU利用率至60-80%。实施效果显示月结时间缩短70%,成功率提升至99.8%,错误恢复时间减少75%。该方案为大型企业ERP系统提供了高效的月结加速方案,未来还将结合AI调度与混合云扩展持续优化。

金牌架构师 1440

浅谈C++结构体的内存对齐

最近在认真学习C++基础,就此对于结构体的内存对齐做个学习笔记

Jovi’s Blog 758

【机器学习与数据挖掘实战 | 商务】案例03:基于k近邻算法的非侵入式电力负荷监测与分解的电力分析

本案例结合非侵入式电力负荷监测与分解的案例,重点介绍了在数据可视化的辅助下k近邻算法的应用。首先利用数据可视化寻找数据的特征,构建特征集合。然后构建k近邻模型,利用构建的特征集合训练模型,接着利用该模型对单一设备所属类别进行判定,最后计算实时用电量。

Morse_Chen的博客 2302

C++之结构体内存对齐

C++之结构体内存对齐 内存对齐原因 首先要知道,cpu是把内存当作一块一块来读取的,块的大小可以是2,4,8,16个字节,这样内存不对齐就可能会导致每次读取数据需要读取两次,内存对齐之后读取一次就行,可以大大提高内存的访问速度。 结构体内存对齐原则 第一个成员在与结构体偏移量为0的地址处 其他成员变量要对齐到对齐数的整数倍的地址处。对齐数=编译器默认的一个对齐数和该成员大小的较小值。VS默认对齐数8,gcc默认对齐数4 结构体总大小:最大对齐数(所有变量类型最大者和默认对齐参数取最小)的整数倍。 如果嵌

qq_44559016的博客 517

【即插即用模块】注意力篇 | TIP 2024 | 注意力机制的有效改进!内容引导注意力块CGA,空间-通道-像素三个维度融合,实现涨点!

CGA(Content-Guided Attention)是一种融合多维度注意力的即插即用模块,通过并联空间和通道注意力并与像素注意力串联,实现从通道、空间到像素的三层级特征筛选。该模块采用层级递进设计,解决了传统单维度注意力的局限性,尤其适用于图像恢复等对特征精度要求高的任务。实验表明,CGA在去雾任务中能显著提升指标,但会略微增加参数量。模块代码支持灵活集成到各类视觉模型中,建议放置在网络靠前位置以充分释放后续层性能。其核心创新在于通过7×7大卷积捕捉长距离依赖,结合分组卷积实现像素级细粒度建模

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 225

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C/C++结构体的内存对齐详解(深入探究结构体在内存里的保存形式)

结构体内存对齐

qq_45315034的博客 1384

jre9下载 jdk9

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

C++面试题:结构体内存对齐

问题答案原因对齐模数4时占用内存12字节按默认4字节对齐,需填充最小占用内存8字节通过调整成员顺序(int → short → char)如何修改对齐模数alignas(1)通过编译器指令或C++11特性为什么不能设为1或21:导致未对齐访问,性能下降;2:无法满足int 4字节对齐要求CPU优化基于对齐内存关键点:内存对齐是CPU和编译器共同决定的,不是程序员随意可以修改的。

2301_80355452的博客 967

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

C/C++中的结构体对齐问题(内存对齐)

C/C++中的结构体对齐问题(内存对齐) 分类: c++ 2009-10-18 17:02 22人阅读 评论(0) 收藏 举报 由于程序运行时占用的内存过大,所以想办法给程序瘦身。 在调试中发现结构体占用的size竟然和预想的不一样,原来…… 看看下面讲的吧,肯定会不枉此看哦! 1,比如: struct{ short a1; short a2; sh

小菜鸟的专栏 956

C/C++:结构体内存对齐

C语言结构体内存对齐

做一只猫的博客 4832

C/C++ 内存对齐(一):结构体

内存管理是C/C++编程非常重要的一部分内容,熟悉C/C++中一些常见数据结构和数据类型的内存分布情况,可以很大程度上降低了coding过程中内存泄漏和越界等比较严重的内存问题,下面主要讨论一下结构体(类中同样存在内存对齐,内存对齐会复杂一些,涉及到虚表等问题,后面介绍类的时候会提到)中的内存对齐问题。

lijian2017的博客 451

C/C++--->结构体内存对齐详解

对齐规则 (1) 第一个成员在与结构体变量偏移为0的地址处. (2) 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数:编译器默认的一个对齐数与该成员大小的较小值(vs中默认值为8,Linux中默认值为4)。 (3) 结构体总大小为最大对齐数的整数倍。 最大对齐数:结构体的每个成员变量都有一个对齐数(该类型的大小),取最大。 (4) 如果嵌套了结构体的情况,嵌套的结构体对齐到自己成员最大对齐数的整数倍,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。 #include.

qq_42069216的博客 627
上一篇: C++ 智能指针 - 全部用法详解
下一篇: C/C++ 二分查找算法(非递归实现)
cpp_learners
博客等级 码龄7年 1526粉丝 274原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cpp_learners

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值