sizeof 算结构体大小,为什么结果总是比我算的大?
一个让我愣住的 sizeof今天晚上继续磕学生管理系统。前面用数组分别存姓名、成绩、年龄搞得我每次改学生信息都要同时操作三个数组代码又臭又长。我就想就不能把跟一个学生相关的所有信息打包在一起吗查了一下C 语言里果然有个东西叫结构体struct专门干这个事。我兴奋地写了第一个结构体定义了一个student类型struct student { char name[20]; // 名字20字节 int age; // 年龄4字节 float score; // 分数4字节 };然后我顺手用sizeof(struct student)看了一下这个类型占多大空间。心里的小算盘打得啪啪响20 4 4 28 字节。结果一跑输出 28运气好还真是 28——但如果我换个成员顺序结果就变了。我当时就愣住了这又不是四则运算怎么换顺序还影响结果后来才知道这不是 C 语言 bug是一个叫结构体对齐的东西在作祟。这是今天花最长时间搞明白的事。先搞清楚结构体到底是什么在这之前先把结构体本身理清楚。int存整数char存字符这些是 C 语言给的基本类型。但真实世界里的数据从来不是一个一个独立存在的——一个学生同时有名字、年龄、成绩你要是还像之前那样用三个数组去存它们之间的联系全靠同一个下标硬撑着。结构体干的事就是自己造一个新的数据类型把要用的成员打包在一起。语法长这样struct 结构体名 { 成员列表; }; // 这个分号千万别忘忘了我已经替你试过了编译器报错能看哭你造好了类型之后用法跟int那种基本类型一样——可以定义变量、数组、指针还能当函数参数和返回值。下面对比一下int a; // 定义一个整数变量开了4字节空间 struct student s; // 定义一个学生变量开多大空间这就是前面的问题了定义变量的本质就是开空间所以空间到底多大自然就成了第一个绕不开的问题。初始化、点运算符和箭头运算符这些倒不复杂初始化就按成员顺序挨个给值struct student s {tom, 18, 99.5}; // 按 name, age, score 顺序来访问成员用.运算符s.name // 访问名字 s.age // 访问年龄 s.score // 访问分数如果用到指针用-运算符更清爽struct student *p s; p-name // 等价于 (*p).name但少打两个字符你懂的有个挺方便的小细节同类型的结构体变量可以直接用赋值成员会逐个拷贝过去不用自己写循环struct student s1 {tom, 18, 99.5}; struct student s2 s1; // 爽一行搞定不过函数传参时要注意一般传地址而不是传结构体本身。你想想一个结构体可能几十上百字节如果传值就会把整个结构体复制一份传给函数浪费时间和栈空间没必要。回到那个让我纠结了一晚上的对齐问题好现在回到开头那个让我怀疑人生的问题为什么sizeof(struct student)不一定等于成员大小加起来我把 student 结构体里的成员换了个顺序来试struct demo { char a; // 1字节 int b; // 4字节 char c; // 1字节 }; // 我心算1 4 1 6 字节 // 实际输出12 字节。喂不是编译器出 bug是 CPU 本身就不喜欢非对齐的数据。32 位 CPU 一次读 4 个字节如果数据没有放在“自然边界”上CPU 可能要多读一次才能完整取出数据。编译器为了性能就自动帮我们做内存对齐。规则分两步第一步每个成员要站在自己的自然边界上。什么叫自然边界就是成员类型大小对应的地址要求char—— 1 字节对齐随意放short—— 2 字节对齐地址必须能被 2 整除int/long/float—— 4 字节对齐地址必须能被 4 整除double—— 8 字节对齐地址必须能被 8 整除。回头看我那个demo结构体char a从地址 0 开始占 1 字节下一个是int b它要求地址必须是 4 的倍数所以地址 1、2、3 都满足不了编译器直接跳过 3 个字节让b从地址 4 开始。然后char c从地址 8 开始。第二步整个结构体的大小要跟最大成员对齐。int b是 4 字节对齐所以整个结构体的大小必须是 4 的整数倍。目前 a(1) 填充(3) b(4) c(1) 9 字节9 不是 4 的倍数编译器又在最后补了 3 字节凑成 12。总的来说结构体大小不是简单把成员大小相加编译器会在成员之间和末尾偷偷塞“填充字节”让每个成员站在自己的自然边界上。听起来很烦但本质上是在帮 CPU 跑得更快。共用体同一个房间不同时间段住不同的人结构体是每个成员各有各的房间共用体union是所有成员轮流用同一间房。语法跟结构体差不多union demo { int a; // 4字节 float b; // 4字节 char c; // 1字节 }; // 三个变量共用一块空间空间大小取最大的那个成员——也就是4字节初始化时只能给一个值默认给第一个成员union demo d {10}; // 给第一个成员 a 赋值为 10这里有个容易踩的坑如果你给d.a 100;然后再给d.c A;那d.a的值就没了——大家住同一间房后面住进来的人会把前面的人的东西清出去。共用体一个经典的用法是测试电脑是大端还是小端union test { int a; char b; }; union test t; t.a 1; // int 和 char 的起始地址相同b 读到的是 a 的最低字节 if (t.b 1) { printf(小端模式\n); // 低位在低地址 } else { printf(大端模式\n); // 低位在高地址 }还有一个实用场景学生有score老师有salary但同一个人不可能同时是学生又是老师所以这俩字段不用同时存在struct member { char name[20]; int age; union { float score; // 学生用 float salary; // 老师用 } data; }; // 省下了一个 float 的空间枚举给那些只有几种可能值的变量正经起个名如果一个变量取值就那么几种比如交通信号灯就红、绿、黄三种。你用0、1、2去代表过两周回来看代码满脑子问号0 是啥意思来着红灯还是绿灯枚举就是来解决这个的enum light { RED, // 默认从 0 开始 GREEN, // 自动 1 YELLOW // 自动 2 };好处很明显代码可读性直接提升一个档次看到RED就知道是红灯不用猜数字。还可以自己指定起始值enum light { RED 10, GREEN, // 接着变成 11 YELLOW // 接着变成 12 };枚举本质是int类型但它跟宏定义比起来有个很大优势枚举是正儿八经的类型编译阶段发挥作用有类型检查宏呢只是预处理阶段做文本替换没有任何类型概念出错了编译器连个像样的提示都给不了。今天容易搞混的几个点容易搞混的情况为什么容易错结构体大小直接用成员大小加编译器会做内存对齐成员之间和末尾可能有填充字节换一下成员顺序结果就可能不一样结构体传参直接传变量本身值传递会把整个结构体复制一份大的结构体浪费栈空间还慢传地址更高效共用体当成结构体来用以为各存各的共用体所有成员共用一块内存给第二个成员赋值会把第一个成员的值覆盖掉共用体大小以为是所有成员之和共用体大小等于最大成员的大小不是加起来的别跟结构体搞混枚举和宏定义混着用感觉差不多枚举有类型检查编译阶段生效宏只是预处理文本替换没有类型概念调试起来更痛苦结构体定义最后忘写分号};这个分号一漏编译器报一堆莫名其妙的错一开始看会特别懵今日学习感悟今天花时间最多的不是写代码是搞清楚 sizeof 为啥对不上我口算的结果。刚开始觉得对齐就是编译器在折磨我后来理解了 CPU 读内存的方式才觉得它确实是在帮我们做优化。结构体、共用体、枚举其实都是在解决同一个问题怎么把数据组织得更合理。用数组硬撑确实能跑但写到后面就知道痛苦了。慢慢开始体会到好的数据结构比多写几行代码重要得多。Day15 学习记录明天继续。

相关新闻

QWENPAW 本地部署实战:结合免费模型配置实现零成本运行

QWENPAW 本地部署实战:结合免费模型配置实现零成本运行

本文介绍 QWENPAW 的本地部署流程,并详细讲解如何配置免费模型(如 Qwen 系列开源权重或 Ollama 托管的轻量模型),通过代码示例与注意事项,帮助读者快速搭建可用环境。 标签:QWENPAW、Ollama、本地部署、免费…

2026/8/1 2:28:56阅读更多 →
ADC前端滤波电容选型误区:大电容为何导致采样失真?

ADC前端滤波电容选型误区:大电容为何导致采样失真?

这次我们来看一个在嵌入式开发和信号采集领域非常普遍,但又容易被误解的问题:ADC(模数转换器)前端的滤波电容,是不是越大越好?很多工程师在设计电路时,会下意识地认为更大的滤波电容能带来更纯净…

2026/8/1 2:28:56阅读更多 →
Linux权限管理完全指南

Linux权限管理完全指南

1. 用户与权限的基本概念在 Linux 系统中,每个文件和目录都属于一个用户(owner)和一个用户组(group)。权限就是对这三类身份分别设定的:用户(user / owner):文件的拥有者…

2026/8/1 2:28:56阅读更多 →
VC++运行库安装指南:从原理到实践,解决DLL缺失问题

VC++运行库安装指南:从原理到实践,解决DLL缺失问题

1. 项目概述:为什么VC运行库是“系统基石”?如果你在电脑上安装过大型软件、游戏,或者运行某些专业工具时,突然弹出一个“无法启动此程序,因为计算机中丢失 VCRUNTIME140.dll”之类的错误,那你已经和VC运行…

2026/8/1 3:45:21阅读更多 →
QT文件操作核心指南:QFile与QFileInfo原理、实战与性能优化

QT文件操作核心指南:QFile与QFileInfo原理、实战与性能优化

1. 项目概述:为什么需要关注QT的文件操作?在桌面应用、嵌入式HMI或者工业控制软件的开发中,文件操作几乎是绕不开的基础功能。无论是读取配置文件、保存用户数据、导出日志,还是处理用户上传的图片文档,你都需要和本地…

2026/8/1 3:45:21阅读更多 →
LangSmith上架谷歌云市场:LLM应用可观测性与工程化新标杆

LangSmith上架谷歌云市场:LLM应用可观测性与工程化新标杆

1. 从LangSmith上架谷歌云市场说起:开发者工具生态的“新基建”竞赛如果你最近在关注AI应用开发,尤其是围绕大语言模型(LLM)构建智能体(Agent)或复杂工作流,那么“LangSmith”这个名字大概率已经…

2026/8/1 3:45:21阅读更多 →
基于LangChain与LangSmith构建医药研发多智能体协作平台实战

基于LangChain与LangSmith构建医药研发多智能体协作平台实战

1. 项目概述:从单点工具到智能协作平台的跃迁 在生物医药这个信息密集、决策链条漫长的领域,研发人员每天都要面对海量的文献、临床试验数据、专利信息和市场报告。传统的做法是,研究员们手动在PubMed、ClinicalTrials.gov、公司年报等数十个…

2026/8/1 3:45:21阅读更多 →
嵌入式软件单元测试:从理论到实践

嵌入式软件单元测试:从理论到实践

1. 引言在嵌入式系统开发中,软件质量直接关系到产品的可靠性、安全性和稳定性。单元测试作为软件测试金字塔的基石,是保障代码质量、减少缺陷、提升开发效率的关键环节。然而,嵌入式软件因其硬件依赖性强、资源受限、实时性要求高等特点&…

2026/8/1 3:45:21阅读更多 →
图吧工具箱 TubaWinUI3:装机佬的“新装备“,这次真的不一样了

图吧工具箱 TubaWinUI3:装机佬的“新装备“,这次真的不一样了

提起"图吧工具箱",老玩家脑海里浮现的可能是那个界面朴素、功能硬核、装机必备的经典工具集。而现在,它迎来了基于 WinUI 3 与 .NET 10 的彻底重构——TubaWinUI3 版本。不是换皮,是从底层到体验的全面升级。 图吧工具箱 TubaWinU…

2026/8/1 3:43:21阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/31 20:44:05阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/31 17:41:43阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/31 20:44:05阅读更多 →
无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 在数字媒体创作领域,视频编辑处理的质量损…

2026/8/1 0:00:10阅读更多 →
AI辅助本科论文写作:8大工具评测与高效使用指南

AI辅助本科论文写作:8大工具评测与高效使用指南

1. 本科生论文写作的AI辅助现状本科毕业论文是每个大学生必须跨越的一道坎。记得我当年写论文时,光是文献检索就花了整整两周时间,打印的参考文献堆满了半个书桌。如今AI技术的发展为学术写作带来了革命性变化,合理使用这些工具可以节省80%以…

2026/8/1 0:00:10阅读更多 →
如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到热门演唱会门票…

2026/8/1 0:00:10阅读更多 →
无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 在数字媒体创作领域,视频编辑处理的质量损…

2026/8/1 0:00:10阅读更多 →
AI辅助本科论文写作:8大工具评测与高效使用指南

AI辅助本科论文写作:8大工具评测与高效使用指南

1. 本科生论文写作的AI辅助现状本科毕业论文是每个大学生必须跨越的一道坎。记得我当年写论文时,光是文献检索就花了整整两周时间,打印的参考文献堆满了半个书桌。如今AI技术的发展为学术写作带来了革命性变化,合理使用这些工具可以节省80%以…

2026/8/1 0:00:10阅读更多 →
如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到热门演唱会门票…

2026/8/1 0:00:10阅读更多 →