C++ 结构体对齐详解

目录

前言

一、为什么要对结构体进行对齐操作?

二、基本概念

三、 对齐规则

四、示例讲解

1.简单的变量对齐

2.结构体包含有结构体的对齐

结构体成员详细解析

五、使用指令改变对齐方式

__attribute__((packed))

#pragma pack(push, n)

#pragma pack(pop)

六、总结


前言

在C++中,结构体(struct)的对齐是指编译器为确保结构体成员在内存中的地址满足特定的对齐要求而进行的调整。对齐有助于提高访问速度,但同时也可能导致内存空间的浪费。


一、为什么要对结构体进行对齐操作?

结构体对齐的主要目的是优化内存访问速度提高内存利用率

二、基本概念

对齐(Alignment):指数据在内存中按照某种边界方式排列。例如,4字节的整数通常按4字节边界对齐。

填充(Padding):为了满足对齐要求而在数据之间插入的无意义的字节。

边界(Alignment Boundary):存储单元的起始地址必须是其大小的整数倍,例如,4字节的整数应该存储在能被4整除的地址上。

三、 对齐规则

编译器通常遵循以下规则来对齐结构体:

  • 每个成员变量的地址都是其自身大小的整数倍。
  • 结构体的总大小是其最大成员大小的整数倍。
  • 编译器可能会插入填充字节以满足上述对齐要求。

四、示例讲解

1.简单的变量对齐

struct Example {char a;   // 1 byteint b;    // 4 bytesshort c;  // 2 bytes
};

编译器将如何对齐和填充这个结构体?假设默认对齐是4字节:

  • char a 占用1字节,开始地址0x00。
  • int b 需要4字节对齐,下一个可以被4整除的地址是0x04,因此在 a 后面插入3个填充值。
  • short c 需要2字节对齐,b 占用4个字节后,c 可以直接放在下一个地址0x08。

所以结构体在内存中的布局如下:

以结构体在内存中的布局如下:

地址内容
0x00a
0x01填充
0x02填充
0x03填充
0x04b
0x05b
0x06b
0x07b
0x08c
0x09c

总大小是10字节,但为了满足最大成员(int)的对齐要求,编译器可能会将结构体的总大小调整为12字节,使其成为4的倍数。

2.结构体包含有结构体的对齐

编译器将根据每个类型的自然对齐需求来安排各个成员的位置,以便优化内存访问。

#include <iostream>struct InnerStruct {char a;   // 1字节int b;    // 4字节
};struct OuterStruct {char c;             // 1字节InnerStruct inner;  // 包含内部结构体double d;           // 8字节
};

结构体成员详细解析

  1. 内部结构体 InnerStruct

    • char a :占用1字节。
    • int b :通常情况下,占用4字节。
  2. 外部结构体 OuterStruct

    • char c :占用1字节。
    • InnerStruct inner :包含了 InnerStruct 类型的内部结构体。
    • double d :占用8字节。
  • 内部结构体 InnerStruct 的对齐

    • char a 占用1字节。由于 int b 需要4字节对齐,所以 a 后面会有3字节的填充,使得 b 能够对齐到下一个4的倍数地址上。
    • 因此,InnerStruct 的总大小将是8字节(1字节 a + 3字节填充 + 4字节 b)。
  • 外部结构体 OuterStruct 的对齐

    • char c 占用1字节。为了对齐 InnerStructc 后面会有3字节的填充。
    • InnerStruct inner 将从4字节边界开始,总共占用8字节(如上所述)。
    • double d 通常需要8字节对齐,因此在 InnerStruct inner 后面可能会有额外的填充字节。

下面是这两个结构体在默认对齐规则下的内存布局示意图:总结20字节

OuterStruct:
| c (1B) | padding (3B) | InnerStruct (8B) | double d (8B) |InnerStruct:
| a (1B) | padding (3B) | b (4B) |

五、使用指令改变对齐方式

可以使用编译器特定的指令或预处理指令来改变结构体的对齐方式。

__attribute__((packed))

例如,在GCC中,可以使用 __attribute__((packed)) 来消除填充:

struct ExamplePacked {char a;int b;short c;
} __attribute__((packed));

在MSVC中,可以使用 #pragma pack(push, n)#pragma pack(pop)

#pragma pack(push, 1)
struct ExamplePacked {char a;int b;short c;
};
#pragma pack(pop)

#pragma pack(push, n)

  • 功能#pragma pack(push, n) 将当前的对齐设置压入一个栈中,并将对齐值设置为 n
  • 参数
    • n:指定新的对齐值(通常是1、2、4、8或16),表示数据成员应该按照 n 字节边界进行对齐。

#pragma pack(pop)

  • 功能#pragma pack(pop) 用于从栈中弹出之前保存的对齐设置,并恢复该设置。

这样做的结果是结构体成员紧密排列,没有填充字节,但会导致性能下降,因为访问未对齐的数据可能需要更多的处理时间。

六、总结

  • 默认对齐:通常情况下,最好使用编译器的默认对齐方式,以获得最佳性能。
  • 手动对齐:只有在明确知道需要节省内存,并且能接受性能损失的情况下才使用手动对齐。

理解和控制结构体的对齐对于编写高效、可靠的C++程序非常重要。希望这篇详解能够帮助你更好地掌握结构体对齐的概念和应用。

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

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

相关文章

Java中如何处理XML数据?

Java中如何处理XML数据&#xff1f; 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨在Java中如何高效处理XML数据的技术和最佳实践。XML&…

Elasticsearch:赋能数据搜索与分析的利器

Elasticsearch&#xff1a;赋能数据搜索与分析的利器 在大数据的时代背景下&#xff0c;如何高效地搜索、分析和利用数据成为了企业和开发者面临的重要问题。Elasticsearch&#xff0c;作为Elastic Stack的核心组件&#xff0c;以其分布式、高扩展性和实时的搜索与分析能力&am…

【CentOS7】Linux安装Docker教程(保姆篇)

文章目录 查看是否已安装卸载&#xff08;已安装过&#xff09;docker安装友情提示 更多相关内容可查看 注&#xff1a;本篇为Centos7安装Docker&#xff0c;若为其他系统请理性参考 查看是否已安装 如果已安装&#xff0c;请卸载重新安装 docker --version这里显示已安装 …

人机的三级抽象

数学的三级抽象包括第一级抽象是数表示万物、第二级抽象是字母表征数、第三级抽象是运算规则的抽象&#xff08;如群论&#xff09;&#xff0c;在人机交互中&#xff0c;类比于数学的三级抽象&#xff0c;可以理解为&#xff1a; 第一级抽象&#xff1a;用户界面和操作的抽象化…

力扣第210题“课程表 II”

在本篇文章中&#xff0c;我们将详细解读力扣第210题“课程表 II”。通过学习本篇文章&#xff0c;读者将掌握如何使用拓扑排序来解决这一问题&#xff0c;并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释&#xff0c;以便于理解。 问题描述 力扣第210题“…

Linux 服务管理

服务(service)本质就是进程&#xff0c;但是是运行在后台的&#xff0c;通常都会监听某个端口&#xff0c;等待其它程序的请求&#xff0c;比如(mysqld , sshd防火墙等)&#xff0c;因此又称为守护进程。 比如通过xshell进行连接的时候&#xff0c;需要输入的端口号就是通过守护…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷8(容器云)

#需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件包…

基于Java图书馆管理系统详细设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

iptables(4)规则匹配条件(源、目、协议、接口、端口)

简介 前面我们已经介绍了iptables的基本原理,表、链,数据包处理流程。如何查询各种表的信息。还有基本的增、删、改、保存的基础操作。 经过前文介绍,我们已经能够熟练的管理规则了,但是我们只使用过一种匹配条件,就是将”源地址”作为匹配条件。那么这篇文章中,我们就来…

[职场] 教师资格面试流程 #经验分享#其他

教师资格面试流程 教师资格证面试流程如下&#xff1a; ①候考。在考试当日&#xff0c;考生按照准考证上的时间进入候考室&#xff0c;进行抽签分组。 ②抽题。考生按照抽签顺序分组安排从面试题库系统试题组中任选其中一道试题&#xff0c;确认抽题后&#xff0c;计算机打印出…

爱心商城管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;企业管理&#xff0c;用户管理&#xff0c;论坛管理&#xff0c;商品管理&#xff0c;公告管理&#xff0c;用户捐赠 企业账户功能包括&#xff1a;系统首页&#xff0c;个人中心…

机器学习(二)

机器学习 3.分类算法3.1 sklearn转换器和估计器3.1.1 转换器3.1.2 估计器(在sklearn实现机器学习算法) 3.2 K-近邻算法3.2.1 什么是K-近邻算法3.2.2 K-近邻算法API3.2.3 案例&#xff1a;鸢尾花种类预测3.2.4 K-近邻总结 3.3 模型选择与调优3.3.1 交叉验证&#xff08;cross va…

LeetCode 70. 爬楼梯 使用c++解答

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1. 1 阶 1 阶 2. 2 阶 示例 2&#x…

【STM32+FPGA】先进算力+强安全+边缘AI,64位STM32MP2聚焦工业4.0应用

工业应用数字化和智能化程度&#xff0c;是衡量新质生产力的重要标准。STM32最新一代64位微处理器STM32MP2凭借先进算力、丰富接口和高安全性&#xff0c;为高性能和高度互联的工业4.0应用赋能。 STM32MP2四大关键特性&#xff0c;为工业4.0应用赋能 STM32MP2系列的第一颗产品S…

XTDrone-无人机与无人船协同初步-配置教程

说明&#xff1a;配置该教程时所使用的是Ubuntu20.04 1 海洋与无人船仿真环境搭建 cp -r ~/XTDrone/sitl_config/usv/* ~/catkin_ws/src/ cd catkin_ws catkin build # or catkin_make 说明&#xff1a;由于官方所编写的脚本时几年之前的&#xff0c;所以很多东西不符合现在…

【Rust日报】Dioxus 团队给Rust未来的期望

让你的第一个Rust严肃应用成功 corrode总结了一份用Rust实现工程的评估清单&#xff0c;为考虑采用Rust编程语言的企业提供了全面指南。以下是主要内容&#xff1a; 评估业务需求和适应性&#xff1a;确定Rust是否符合公司技术需求和长期目标。评估Rust的性能和安全特性在具体用…

Git的安装以及使用

一.简单介绍 1.1版本控制 版本控制是指对软件开发过程中各种程序代码,配置文件及说明文档等文件变更管理&#xff0c;是软件配置管理的核心思想之一。 版本控制最重要的内容是追踪文件的变更&#xff0c;它将什么时候&#xff0c;什么人更改了文件的什么内容等信息忠实的记录…

面向二级及二级以下医院的云HIS系统源码,涵盖患者、费用、医嘱、电子病历等核心业务功能。

云HIS系统源码&#xff0c;二级医院信息管理系统源码&#xff0c;电子病历系统 云HIS系统&#xff0c;采用云计算、互(物)联网、大数据、人工智能等现代信息技术&#xff0c;融合医保、医疗、医药全方位的管理和服务&#xff0c;为各类中小型医疗机构&#xff0c;包括二级及二…

B3996 [洛谷 202406GESP 模拟 三级] 小洛的数字游戏

题目描述 小洛有一个正整数 &#x1d45b;n&#xff0c;他会进行若干次下列操作&#xff1a; 取出正整数 &#x1d45b; 的末位&#xff0c;记作 &#x1d465;&#xff1b;将 &#x1d465;平方之后&#xff0c;保留个位&#xff0c;放于 &#x1d45b; 的首位之前&#xff…