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/10/17 23:41:10 阅读更多 →
ADC前端滤波电容选型误区:大电容为何导致采样失真?

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

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

2026/10/17 13:21:18 阅读更多 →
Linux权限管理完全指南

Linux权限管理完全指南

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

2026/10/14 9:13:45 阅读更多 →

最新新闻

对抗扩散蒸馏实战:三重损失把扩散模型压缩到一两步出图

对抗扩散蒸馏实战:三重损失把扩散模型压缩到一两步出图

对抗扩散蒸馏,简单说就是把大模型上那种几十步才能出图的扩散过程,硬生生压缩到一两步甚至一步出图,同时尽量保住画面质量和多样性。这个方向我从年初就开始关注,前前后后在几个文生图项目里试过好几版实现,踩了不少坑…

2026/10/18 20:45:16 阅读更多 →
Ruby on Rails 机票电商源码拆解:从搜索到出票的完整链路与二次开发指南

Ruby on Rails 机票电商源码拆解:从搜索到出票的完整链路与二次开发指南

简介:eyoo:旅游机票电商平台(重构版)是一份基于Ruby技术栈的在线机票销售系统源码,面向具备一定Web开发基础、希望深入理解电商平台架构的开发者与学习者。项目以Ruby on Rails为核心,涵盖MVC分层、ActiveRecord数据库…

2026/10/18 20:45:16 阅读更多 →
XAudio2_3.dll丢失不用慌:看清原理,微软官方方案一次搞定

XAudio2_3.dll丢失不用慌:看清原理,微软官方方案一次搞定

最近我的电脑在运行一款老游戏时突然弹窗提示“无法启动,因为计算机丢失XAudio2_3.dll”,紧接着音频就没声了,游戏直接崩掉。后来帮几个朋友远程排查时发现,这个问题其实相当普遍,而且绝大多数人第一反应都是去搜索引擎…

2026/10/18 20:45:16 阅读更多 →
从信息猎人进化到资产哨兵:Google与GitHub搜索语法实战

从信息猎人进化到资产哨兵:Google与GitHub搜索语法实战

1. 破题:这不是攻击教程,而是防御者的资产排查清单看到"Google/GitHub Hacking"这个标题,可能有人会下意识认为这是攻击者的技巧合集。我先说清楚我的立场:我在这里讲的是防御视角的主动暴露面排查——也就是用搜索语法…

2026/10/18 20:45:16 阅读更多 →
Python检测Windows窗口句柄信息:枚举、解析与避坑指南

Python检测Windows窗口句柄信息:枚举、解析与避坑指南

简介:Python自动化开发中,窗口句柄获取是桌面端自动化测试与系统监控的常见需求。面向有Python基础、正着手Windows窗体交互开发的学习者或测试工程师,内容演示如何通过pywin32封装库枚举窗口、依据标题或类名匹配句柄,并支持对窗…

2026/10/18 20:45:16 阅读更多 →
计算机网络综合实验方案:VLAN、OSPF、NAT与抓包分析全链路

计算机网络综合实验方案:VLAN、OSPF、NAT与抓包分析全链路

简介:这份华北电力大学计算机网络综合实验报告配套资料,面向计算机、网络工程等专业学生及需要完成课程设计的学习者,聚焦网络设备配置与协议分析两大实践方向。资源包内含1个doc文档,约21.91MB,完整呈现实验任务书、设…

2026/10/18 20:44:14 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →