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 学习记录明天继续。

相关新闻

最新新闻

开源大模型迎来Claude时刻:GLM-5.2与Mythos深度评测与部署指南

开源大模型迎来Claude时刻:GLM-5.2与Mythos深度评测与部署指南

1. 项目概述:当开源模型迎来“Claude时刻”最近在AI社区里,一个非常有意思的现象正在发生:大家开始把智谱最新发布的GLM-5.2模型,和一个名为“Mythos”的开源模型放在一起讨论,甚至有人称之为“开源Claude时刻”。这个…

2026/8/1 3:34:05
Hive表结构变更实战:ALTER TABLE核心操作与Schema演化最佳实践

Hive表结构变更实战:ALTER TABLE核心操作与Schema演化最佳实践

1. 项目概述:Hive表结构变更的实战指南在数据仓库的日常运维和数仓开发中,我们几乎每天都要和数据表打交道。Hive作为构建在Hadoop之上的数据仓库工具,其表结构的灵活性直接关系到数据模型的迭代效率和数据应用的稳定性。很多刚接触Hive的同学…

2026/8/1 3:34:05
TM1650驱动四位数码管:I2C接口应用与单片机代码实现

TM1650驱动四位数码管:I2C接口应用与单片机代码实现

1. 项目概述:从点亮一个段到驱动四位数字如果你玩过单片机,大概率不会对数码管感到陌生。从简单的电子钟、温湿度计,到工业仪表、家用电器,这种由多个发光二极管(LED)组成的显示器件无处不在。单个数码管驱…

2026/8/1 3:34:05
数字化打卡系统:习惯养成的行为心理学与工具实践

数字化打卡系统:习惯养成的行为心理学与工具实践

1. 项目概述"3/26打卡"这个看似简单的标题背后,实际上反映了一个普遍存在的现代人需求——习惯养成与自我管理。作为一个长期关注效率工具和习惯养成的实践者,我发现日期打卡的组合形式,往往代表着一种个人成长记录系统。在快节奏的…

2026/8/1 3:34:05
皮尔逊相关系数:从计算到统计推断的完整指南

皮尔逊相关系数:从计算到统计推断的完整指南

1. 项目概述:从“算出来”到“信得过”的相关系数在数据分析、机器学习甚至是日常的科研工作中,我们常常需要量化两个变量之间的关系。是强相关还是弱相关?是正相关还是负相关?这时,皮尔逊相关系数(Pearson…

2026/8/1 3:34:05
一键下载美国专利,就这么简单

一键下载美国专利,就这么简单

在工作中需要下载美国专利的朋友,不用东奔西跑到处找地址下载。美国官网不好用,速度慢,不英文不好的不好操作,目前 网络上有好多美国专利下载的软件都已经失效了,只有灰灰美国专利下载软件目前持续可用。免费下载地址&…

2026/8/1 3:29:04