当前位置: 首页 > news >正文

C/C++结构体内存的问题

1.结构体内存布局的基本规则

1.1.成员顺序

结构体的成员在内存中按照声明的顺序依次存放。第一个成员的地址与结构体的地址相同。

struct Example { char a; // 1字节 int b; // 4字节 double c; // 8字节 short d; // 2字节 };

1.2 对齐要求和结构体大小的计算

结构体的大小不是简单地将所有成员的大小相加,而是要考虑对齐和填充。每个基本类型(如int、double、指针等)都有对齐要求。对齐要求通常是该类型的大小(以字节为单位)或者是编译器特定的值。例如,在大多数系统上,int的对齐要求是4字节,double的对齐要求是8字节。

内存对齐:

内存对齐是通过在数据间填充少量字节,使数据的起始地址满足 CPU 字长(32 位为 4 字节、64 位为 8 字节)或数据自身大小的整数倍的内存布局规则,其核心意义在于:以牺牲少量内存形成内部碎片为代价,既大幅提升 CPU 按访问单元批量读取内存的效率(避免非对齐时多次读取、拼接数据的额外开销),又能兼容不支持非对齐访问的硬件(如早期 ARM 处理器)以防止程序崩溃,同时还能避免数据跨 CPU 访问单元存储引发的截断、乱码等问题,保障数据存储的完整性与稳定性。

默认对齐规则

(无 #pragma pack,编译器默认行为)

数据类型分类对齐值计算规则64 位系统示例(对齐值 / 大小)32 位系统示例(对齐值 / 大小)
基本数据类型对齐值 = 该类型的「字节大小」(大小就是 sizeof 的结果)char:1/1short:2/2int:4/4double:8/8同 64 位(基本类型大小不变)
指针类型对齐值 = CPU 字长(64 位 = 8,32 位 = 4),与指向的类型无关int*:8/8char*:8/8double*:8/8int*:4/4char*:4/4
数组类型对齐值 = 「数组元素的对齐值」(数组整体大小不影响对齐值,只影响占用空间)char arr[5]:1/5int arr[3]:4/12double arr[2]:8/16同 64 位(元素对齐值不变)
结构体(struct)对齐值 = 其「所有成员对齐值的最大值」(和成员大小无关,只看成员的对齐值)

示例:

struct S {char c; double d;}对齐值 = max (1,8)=8

同 64 位(成员对齐值不变)
联合体(union)对齐值 = 其「所有成员对齐值的最大值」(和成员大小无关,只看成员的对齐值)

示例:

union U {int a; char b[5];}对齐值 = max (4,1)=4

同 64 位(成员对齐值不变)
嵌套结构体对齐值 = 该嵌套结构体「自身的对齐值」(而非嵌套结构体的大小)

示例:

struct Sub {char a; double b;}

// Sub对齐值 8

struct S {char c; Sub s;}

// S 的对齐值 = max (1,8)=8

同 64 位
计算规则:

规则1:如果你有一个成员_e(大小为x字节对齐值假设也为x字节)需要加入到相对结构体起始地址0偏移y byte的位置那么需要校验y是否为对齐值x的整数倍,若不为整数倍则需加最少的n字节,使得(y+n)%x = 0;
规则2:结构体总大小必须是最大对齐值的整数倍, 而非成员大小的最大值.
规则3:若类有虚函数或者虚继承,则编译器会隐式地加一个虚函数指针的大小在开头;若继承多个不同类型的父类,则会继承到多个虚函数表指针. 这些虚表指针需要计入类的大小。

基本示例:
struct Example1 { char a; // 1字节 int b; // 4字节 double c; // 8字节 }; // 由于内存对齐,可能是16字节 struct Example2 { char a; // 偏移0 double b; // 偏移8(不能放在1) char c; // 偏移16 }; // 总大小24字节(不是17,因为24是8的倍数) // 内存布局: // [a][填充7字节][b(8字节)][c][填充7字节] class MyClass { private: int a; // 4字节 double b; // 8字节 static int c; // 不计入对象大小 public: void func() {} // 函数不计入对象大小 };

2.一些案例

关于嵌套结构体:

struct Inner { int x; // 4字节 char y; // 1字节 // 填充3字节 }; // 大小: 8字节 struct Outer { short a; // 2字节 // 填充2字节 Inner inner; // 8字节 (从4字节边界开始) char b; // 1字节 // 填充7字节 }; // 大小: 24字节

3.一个特殊用法!!!

对于任何一个结构体,可以获取到任何一个元素相较于结构体起点的偏移量:

&((struct A*)0->_element)

结构体指针指向的就是结构体的起点, 同时此起点有和起始元素的地址相同;

只要我们拥有结构体某一个元素的指针,那么就可以用这个指针加上偏移量得到整个结构体的指针

可以用预处理指令定义一个宏offsetof:

#define offsetof(TYPE, MEMBER)((size_t)&((TYPE *)0)->MEMBER)

4.大小端问题

结构体本身并不决定字节序(大端或小端)也不参与字节序, 字节序是由底层的硬件架构决定的。结构体的内存布局中, 成员按照声明顺序排列(考虑对齐), 但每个成员内部的字节顺序则取决于系统的字节序

大端存储(Big-endian):高位字节存储在低地址, 低位字节存储在高地址
小端存储(Little-endian):低位字节存储在低地址, 高位字节存储在高地址

/* 结构体内部遵循硬件平台的字节序 x86/x64架构:小端序 ARM(可配置):通常小端序 PowerPC、SPARC:大端序 网络字节序:大端序 */
http://www.jsqmd.com/news/1333990/

相关文章:

  • 5大核心修复技术:SilentPatch让经典GTA游戏在现代系统上重生
  • 高效在线考试怎么选?告别组卷阅卷耗时长难题 2026 年 08 月 - 讲清楚了
  • iview table columns.js 表头 带* 带星 renderHeader
  • AssetStudio极速入门:3分钟掌握Unity资源提取与导出
  • 三级心理咨询师报考实证解析:从课程设计看职业化路径 - 资讯报道
  • mir_eval性能优化:处理大规模音频数据集的高效方法
  • 2026 年金华沙发翻新沙发换皮,家具维修避坑实测分享 - LYL仔仔
  • EuroSAT遥感数据集:从入门到精通的完整实践指南
  • Lunalytics路线图详解:即将推出的5大重磅功能预览
  • react-native-youtube-iframe播放商店兼容性:避免应用被拒的关键技巧
  • forensictools实战演示:如何通过命令行无缝调用取证工具
  • 数据接口实战:从HTTP API到硬件I2S的采集策略与反反爬技巧
  • 赋能高分子颗粒高效包装,广州恒尔高分子颗粒全自动吨袋包装机以全自动化流程,提升企业核心竞争力 - 品牌速递
  • 辽宁粉笔凭什么更强:一套体系与三种模式的差距 - 资讯报道
  • 解决GIS数据与3D可视化集成的BlenderGIS实战指南
  • 2026景德镇珠山区防水维保一站式服务指南 - 超人防水
  • Kronos:基于项目级上下文理解的AI编程代理实战指南
  • 多语言支持轻松实现:Google App Engine Boilerplate国际化(i18n)配置教程
  • 2026沈阳北师大版数学同步资料哪个好?别再盲目买全国版了 - 资讯报道
  • 革命性图像降噪工具:mlx-community/Restormer-real-denoising-fp32让Apple Silicon焕发新生
  • 科技查新报告怎么查询真伪?编号、盖章和验证方式说明
  • 2026年最新热机械分析仪/材料检测设备/非标试验机生产厂家综合实力解析-承德科承可圈可点 - 自由和远方
  • SynCamMaster快速上手指南:3步实现多摄像头视频同步生成
  • forensictools工具清单详解:从二进制分析到内存取证的12大分类全览
  • 一分钟内从提示词生成仪表板,成本降低 5 倍:Kibana 中的 AI 仪表板和自定义 Vega-Lite 图表
  • 2026年湖北专利申请找哪家?推荐专业代理机构卓越志诚(附FAQ) - 互联网科技品牌测评
  • 榆林2026.8月家里房子漏水怎么办?市面上多种方案可选择,哪种最适合自己?专业防水公司免费上门为您评估,家里漏水不再愁 - 超人防水
  • 雄安2026.8月家里房子漏水怎么办?市面上多种方案可选择,哪种最适合自己?专业防水公司免费上门为您评估,家里漏水不再愁 - 超人防水
  • DeepResearcher框架全面解析:如何通过强化学习实现真实世界环境中的深度研究能力
  • 3个关键步骤让你轻松上手ESP32 Arduino开发