结构体对齐

结构体对齐详解 1.结构体基础知识 a.认识结构体 结构是一些值的集合,这些值称为成员变量.结构的每个成员可以是不同类型的变量. //声明一个结构体类型 //声明一个学生类型(Stu就是你对这个结构体的称呼) struct Stu { char name[20]; char tele[12]; //成员变量 char sex[10]; int age; }s4,s5,s6;//全局变量 struct Stu s3;//全局变量 int main() { //创建结构体变量(局部的) struct St 阅读详情

C/C++ 结构体内存对齐 四大核心原则(MSVC/GCC通用)

一、前置概念

  1. 对齐模数:每个类型自身的天然对齐值(等于该类型占用字节数)
    • char:1,short:2,int/float:4,long long/double:8,指针:8(64位)
  2. 对齐单位:默认等于结构体最大基础成员的对齐模数;也可通过 #pragma pack(n) 手动指定n(1/2/4/8…)
  3. 填充Padding:编译器自动插入空白字节,满足对齐规则,不存储数据

二、完整四条对齐规则(按执行顺序)

规则1:每个成员的起始地址,必须是「自身对齐模数」的整数倍

对结构体里任意成员T m:
m的起始地址 % sizeof(T) == 0

  • 例:int占4字节,只能放在地址0、4、8、12…
  • 例:char占1字节,任意地址都合法,无限制

规则2:成员依次顺序摆放,不重排

成员按代码书写从上到下依次分配内存,不会自动调换顺序;
前一个成员结束后,若下一个成员地址不满足规则1,中间插入Padding空白。

规则3:结构体整体总大小,必须是「当前对齐单位」的整数倍

对齐单位 = min(最大成员天然对齐值, pack指定n)
结构体尾部不足的地方,编译器自动追加尾部Padding补齐。

规则4:#pragma pack(n) 手动压缩对齐(覆盖默认规则)

指定pack(n)后,每个成员的有效对齐模数 = min(类型自身大小, n)

  • #pragma pack(1):无任何填充,所有成员紧挨着存放;
  • #pragma pack(2):int原本对齐4,现在对齐模数变为min(4,2)=2;
  • 使用完必须 #pragma pack() 恢复默认对齐,避免影响其他结构体。

三、用你刚才的结构体举例实操验证

struct node
{
    char a; // 1字节,对齐模数1
    char b; // 1字节,对齐模数1
    char c; // 1字节,对齐模数1
    int s;  // 4字节,对齐模数4
};
  1. 对齐单位:最大成员int=4
  2. 内存分配:
    • a:地址0(1字节)
    • b:地址1(1字节)
    • c:地址2(1字节)
    • 下一个地址3,int要求地址%4==0,不满足 → 插入1字节Padding(地址3)
    • s:地址4~7(4字节)
  3. 当前占用0~7共8字节,8是对齐单位4的整数倍,无需尾部填充
  4. 最终sizeof(node)=8,和你运行结果一致

如果加 #pragma pack(1)

对齐单位=1,所有成员无需填充:
a(0),b(1),c(2),s(3~6),总大小7,7是1的倍数,无尾部Padding。


四、嵌套结构体对齐补充规则

如果结构体包含另一个结构体成员:

  1. 子结构体的对齐模数 = 子结构体自身整体对齐单位
  2. 父结构体的最大对齐单位,会同步更新为「所有基础类型、子结构体对齐模数」中的最大值

示例:

struct Sub{ char c; int i; }; // Sub大小8,对齐模数4
struct Test{
    char ch;    // 1字节
    Sub subobj; // 子结构体,对齐模数4
};
  • ch存地址0;地址1、2、3填充3字节;subobj从4开始;总大小12。

五、速记总结

  1. 每个变量起始地址,必须是自己大小的倍数;不够就中间填空;
  2. 成员顺序不变,从上往下排;
  3. 整个结构体总大小,必须是最大成员对齐值的倍数,不够末尾填空;
  4. pack(n)会限制所有类型最大对齐为n,可压缩内存。

#include <windows.h>
#include
using namespace std;
#pragma pack(16)
struct node
{
char a;
char b;
char c;
int s;

};
int main()
{
node s;

cout << sizeof(node) << endl;
cout << &s << endl;

cout << (void*)&(s.a) << endl;
cout << (void*)&(s.b) << endl;
cout << (void*)&(s.c) << endl;
cout << (void*)&(s.s) << endl;
return 0;

}
8
000000B7F038F740
000000B7F038F740
000000B7F038F741
000000B7F038F742
000000B7F038F744

D:\VSCODE\test\x64\Release\test.exe (进程 32880)已退出,代码为 0。
按任意键关闭此窗口. . .

为何还是8

核心原因:#pragma pack(n) 只是上限约束,不会强行扩大对齐

1. 先明确 pack 的核心公式

对任意成员类型 T:
该成员实际对齐模数 = min( sizeof(T), pack设置的n )

你写了 #pragma pack(16):

  • char 占1字节:min(1,16) = 1
  • int 占4字节:min(4,16) = 4

和默认无pack时的对齐模数完全一样,所以填充、总尺寸不会发生任何变化。

2. 一步步推演内存布局(和不加pack(16)完全相同)

struct node
{
    char a; // 地址0,对齐1
    char b; // 地址1,对齐1
    char c; // 地址2,对齐1
    int s;  // 对齐模数4,要求起始地址 %4 == 0
};
  1. a(0)、b(1)、c(2) 占用前3字节;
  2. 下一个空闲地址是3,3%4≠0,插入1字节填充(地址3);
  3. int s 从地址4开始,占用4、5、6、7;
  4. 结构体总占用 0~7,一共8字节;
  5. 整体对齐单位 = min(最大成员4, pack16) =4,8是4的整数倍,无需尾部填充。
    最终 sizeof(node)=8。

3. pack(n) 两种效果区分

情况1:pack(n) ≥ 类型自身大小(你现在的场景 pack=16 ≥ 4)

pack 仅作为对齐上限,不会改变原有对齐规则,结构体大小不变。

  • #pragma pack(8) / #pragma pack(16) / 不写pack,对这个结构体结果完全一致,都是8字节。

情况2:pack(n) < 类型自身大小(压缩对齐,才会改变尺寸)

举例 #pragma pack(1):
int对齐模数变为 min(4,1)=1,s可以直接放在地址3,无中间填充;
总字节:1+1+1+4 =7,sizeof(node)=7。

4. 补充:什么时候 pack(16) 才会生效?

只有结构体里存在大于4字节的成员(long long/double/指针,天然对齐8)时,pack(16)才会体现上限作用:

#pragma pack(16)
struct Test{
    char ch;
    long long ll; // 天然对齐8,min(8,16)=8
};

此时对齐模数仍为8;如果写 #pragma pack(4),long long对齐模数会被压缩为4。

5. 一句话总结

#pragma pack(16) 只是规定所有成员对齐不能超过16,但你的int本身只需要4字节对齐,上限16不会改变原有填充逻辑,因此结构体大小依旧是8。
想要改变尺寸,必须设置 pack(n) 小于成员天然对齐值(比如pack(1)、pack(2))。

C语言结构体对齐,超详细,超易懂 结构体对齐规则 结构体的第一个成员总是存放在结构体变量开辟的空间的起始地址 其它成员变量要存储在一个名叫对齐数的整数倍的地址 结构体总大小为最大对齐数的整数倍,结构体内每一个变量都会产生一个对齐数,取其最大的对齐数 如果是嵌套结构体,那么嵌套的结构体存储在嵌套结构体的成员的最大对齐数的整数倍地址处,包含嵌套结构体的结构体大小为自己成员的对齐数和嵌套结构体的成员的对齐数的最大对齐数的整数倍 阅读详情

相关推荐

C语言——结构体内存对齐规则

C语言结构体内存对齐规则: 1. 第一个成员在与结构体变量偏移量为0的地址处。 2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。 4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。 附1: 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8 接下来楼主用一些例子来帮助大家理解结构体对齐规则(注:楼..

weixin_53811859的博客 7410

结构体对齐-C语言

(解释一下这句话就是,s3 是嵌套的结构体,它内部最大的对齐数是 8,因为 d 的对齐数是 8,c 的对齐数是 1,i 的对齐数是 4,取其最大的对齐数,那么 s3 的对齐数就是 8,此时vs默认对齐数是8 ,两者取其较小值,所以 s3 这个变量最终被存储在偏移量为 8 字节整数倍的地址处)。c2 是 char 类型,为 1 个字节,默认对齐数是 8,取其较小值为 1,所以 c2 需要被存储到结构体变量对应偏移量为 1 字节整数倍的地址处,这里就直接向后存储就行,因为 9 是 1 的倍数。

m0_73969113的博客 4223

浅析结构体对齐

浅析结构体对齐,用平白易懂的话做分享

轻谈往事的博客 2247

C语言——结构体(struct)对齐

本文主要介绍C语言中,结构体的对齐规则、如何改变对齐数,对齐规则对内存的影响以及如何减小结构体占用的内存。了解结构体的对齐规则对于提高内存使用效率、保证访问速度、避免硬件异常以及提高代码的可移植性都具有重要意义。在编写涉及结构体操作的代码时,我们应该了解和考虑这些对齐规则。

脑壳有点痒,好像要长脑子了! 1万+

VN5620硬件接口介绍

VECTOR, VN5620, 诊断

Fecostar的博客 7488

VMware Workstation Pro 16 安装 Ubuntu 20.04

VMware Workstation Pro 16 安装 ubuntu 20.04目录环境VMware Workstation下载Ubuntu 20.04下载安装过程 目录 环境 Windows 10 Workstation 16 Pro for Windows Ubuntu 20.04 LTS 64位 desktop版本 VMware Workstation下载 链接: https://www.vmware.com/products/workstation-pro/workstation-pro-eval

qq_45642410的博客 1万+

结构体为何要进行对齐以及如何对齐

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

m0_45190002的博客 3217

Silvaco Atlas入门指南——从零开始掌握半导体器件仿真

本文为Silvaco Atlas半导体器件仿真软件的入门指南,详细介绍了从零开始掌握该工具的核心流程。内容涵盖Atlas的基本概念、仿真流程、核心文件(输入、结构、输出文件)、交互式与批处理两种操作模式,并逐步演示了如何从定义网格、划分区域、设置电极到进行掺杂、选择物理模型并求解,最终获取和分析器件特性的完整步骤。旨在帮助微电子相关专业人员和工程师快速上手这一强大的“数字实验室”,提升半导体器件设计与研发效率。

weixin_29306317的博客 403

结构体内存对齐

int a;char b;char c;char b;int a;char c;思考一下node1和node2的大小分别为多少?我是在 Windows 下 MinGW32 的 GCC 测试的一样的成员属性,但node1只有 8K,而node2的大小却有 12K。由此可见,结构体对齐,实质上就是内存对齐。

Projectsauron 的博客 2万+

速腾聚创激光雷达复现FAST-LIO

记录复现FAST-LIO算法的过程和,代码梳理和理解。FAST-LIO的简化版、注释版。速腾激光雷达

abanchao的博客 2932

告别算力焦虑:手把手教你用华为CloudMatrix384超节点部署MoE大模型(附xDeepServe配置)

本文详细解析了如何在华为CloudMatrix384超节点上高效部署MoE大模型,通过xDeepServe框架配置和专家分配优化,实现2300 Tokens/s的推理吞吐。文章涵盖环境准备、性能调优、成本平衡及容灾设计,帮助开发者告别算力焦虑,提升AI推理效率。

weixin_30790841的博客 443

详解结构体对齐

结构体对齐是C语言中的一个重要概念,它决定了结构体成员在内存中的存储方式。

顾得泉的博客 1427

DeerFlow 系列教程 第三篇 | 核心技术深度剖析:Skills、Memory 与 Context Engineering

摘要化是 Context Engineering 中最关键的组件——它直接决定了长对话的可用性。Skills 技能系统通过渐进式加载的三层模型,在保持系统提示词轻量的同时,支持无限数量的技能扩展。从发现到执行的 10 个生命周期阶段,配合 AI 驱动的安全扫描和多层缓存,构成了一个生产级的技能管理框架。Memory 长期记忆系统通过文件系统持久化、LLM 驱动的信息提取和防抖动异步更新,实现了跨会话的认知持久化。六类事实分类体系和修正信号检测机制,让 Agent 能够从交互中持续学习和改进。

weixin_43674738的博客 280

结构体的对齐规则及举例

结构体对齐规则及举例结构体概念结构体声明结构体对齐规则C++中的结构体struct---类 结构体概念 一种数据结构; C语言中聚合数据类型的一类; 可以被声明为变量、数组、指针等,用以实现比较复杂的数据结构; 是一系列元素的集合,这些元素被称为结构体成员; 结构体成员需要用结构体名访问。 结构体声明 struct A{ //struct是关键字, A是结构体标志 int a; //a,b是结构体成员列表 char b; }s1; //s1是结构体变量 注意事项: 一般

weixin_45905650的博客 3745

传统(经典)粒子群算法(PSO)解决单目标优化问题

智能算法:粒子群算法(particle swarm optimizer)—PSO %原理:(1)种群初始化–N(种群数)–D(个体数)–x(i)(粒子位置)–v(i)(粒子速度) % (2)计算每个粒子的适应度值–而适应度值需要选择适应度函数 % (3)对于每个粒子,使用它的适应度值fit[i]和个体的极值pbest(i)进行比较,如果fit[i]>pbest(i),则pbest(i)=fit[i] % (4)同理,对每个粒子用它的适应值与全局极值进行比较,如果比它大,则

weixin_51631044的博客 1295

【数据集】1980-2020年(5年)土地利用分类数据-中国科学院

简介1980-2020年每五年土地利用数据-中国科学院

WW、forever的博客 3935

结构体嵌套对齐以及结构体中含有数组的对齐,也基本总结了各类结构体对齐的问题

基本的结构体对齐知识点击这里 ①结构体嵌套对齐以及结构体中含有数组的对齐 32位系统环境 规则一:结构体中含有数组,数组元素类型和结构中其余的最大类型取较大者 对齐 规则二:结构体S2中嵌套结构体S1,则按照S1的最大元素类型和S2中各元素类型取较大者对齐 就是max(sizeof(struct S1),sizeof(max_type_of_S2)) 注释的数字表示偏移量(就是地址) #include<iostream> #include<vector> struct S1 { c

weixin_46028606的博客 4776

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

结构体对齐总结

结构体对齐结构体对齐到底是什么,看了网上很多的解答,汇总成个人经验什么是结构体对齐结构体对齐规则考虑一个问题,为什么要设计内存对齐的处理方式呢?ENDING 结构体对齐到底是什么,看了网上很多的解答,汇总成个人经验 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 什么是结...

joy2017的博客 2144

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

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

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

上一篇: const int *
下一篇: C++模板
越甲八千
博客等级 码龄11年 2959粉丝 553原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值