news 2026/8/17 19:54:48

纯干货一文搞定结构体

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
纯干货一文搞定结构体

1. 引文

C语言中已经有很多内置类型,如:char,int,float,double等等,但是只有这几个内置类型是远远不够的,假如我们需要描述一个学生的基本信息,这只靠一个内置类型是不行的。

C语言为了解决这种问题,增加了结构体这种自定义的数据类型,让程序员可以创建适合的类型。

结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

2. 结构体

2.1 结构体的声明

C语言中我们使用struct来定义结构体,不能直接用结构体名当类型,需要加 struct。

括号里面的就是成员变量;我们用实例来分析:

struct是结构体的关键字,Stu是结构体的名字,大括号里面定义的变量是成员变量,至于括号外面的s3和s4就是创建的结构体变量,这种创建结构体变量的方法比较简洁,如果这种创建方式是放到main函数里面的话就是创建的局部变量,我们也可以使用其他的创建方法:

注意无论是那种创建方法都大括号外面都必须用分号结尾。

2.2 结构体变量的创建和初始化

创建的话还是很简单的,就是注意分号,初始化有两种初始化的方式,一种是按照结构体的成员变量的顺序来进行初始化,这种方式十分简便;还有一种就是不按成员变量的顺序初始化,这种方式需要我们将被初始化的成员变量的名称也写上,这里注意一下:名称前面有一点,这点千万不要忘记了;初始化时我们可以不写结构体变量名,但是我们在打印的时候必须写上结构体变量名。

结构体是支持循环嵌套的。

2.3 结构体成员的直接访问和间接访问

我们前面的结构体变量.成员名,这就是直接访问。

有时候我们得到的不是⼀个结构体变量,而是得到了⼀个指向结构体的指针。这时候我们就要通过间接访问。

这种结构体指针->成员名,这就是间接访问的形式,注意这里是指针

2.4 结构体的特殊声明

这种没有命名的结构体类型只能使用一次。

但是如果要想长期使用,我们可以对匿名结构体进行重命名:

使用typedef进行类型重命名,注意并不是只有匿名结构体时才能使用typedef来进行重命名,使用已有名称的结构体使用typedef来重命名可以省去每次创建结构体变量都要敲struct:

这里跟我前面的重命名方式有点不一样,这是另一种方式:

但是我那种也没错。

2.5 结构体的自引用

自引用就是结构体里面包含(指向自身类型的指针)。

注意:只能放指针不能直接放结构体变量(如果放结构体变量那就会无限套娃,内存大小根本无法计算)。放入指针,指针的大小是固定的。

结构体一般是结合typedef来一起使用的,这是我们后续学习链表的基础。

typedef在别名没有生效之前不能省略struct,这也就导致匿名结构体不能进行自引用。

2.6 结构体内存对齐

我们已经基本掌握结构体的使用方法了,接下来我们要讨论一个问题:结构体的内存大小怎么计算?

结构体有专门的对齐规则,这些规则你光看是没有一点用的(但是要记住,配合案例理解性记忆),我们直接上实践:

根据这个例子,我们一步一步套公式,分析为什么会是12和8,明明结构体里面我们认为只有6个字节,为什么将顺序换了一下之后,结构体的字节大小也会变?

S1的内存分布图

首先,第一个成员对齐结构体变量起始位置偏移量为0的地方,这个是固定的必须对齐,c1是char类型占1个字节,第二个成员,首先要求对齐数,我们使用的vs编译器默认为8,i是int类型,所以对齐数是8和4中的较小值,也就是4,然后找到对齐数的最小的整数倍的地方也就是4的那块空间,int类型是占4个字节的所以从4开始填充到7的位置,同样的道理,c2的对齐数是1,即找到1的最小倍数位置,每一个都是1的倍数所以就在7的旁边,这时候你数数也就只有9个字节的空间,为什么输出结果是12呢?这时候我们还有第三条,结构体总大小等于最大对齐数的整数倍,前面的c1,c2和i中对齐数最大的是i,最大对齐数是4,我们已经9个字节空间了,最近的4的倍数就是12了,这也就是输出结果了。

同理,我将S2的图画出来,你们试试推出输出结果来。

2.7 为什么存在内存对齐的情况

不知道你们有没有发现在我们在求结构体总大小时,没有填充的空间都是属于浪费的,我们为什么要浪费呢?

我们不是平白无故的浪费,是用这点空间来换取时间上的加速。

那我们怎么满足既要对齐,又要节省空间呢?

我们前面的S1和S2中的成员变量只是因为顺序不一样就导致空间大小也不一样,所以我们还是有方法使得既要对齐又能节省空间的。

我们可以将占用空间小的放到一起

2.7.1 修改默认对齐数

导致内存空间浪费的原因还有一个:就是默认对齐数,通过缩小对齐数,可以减少填充,压缩结构体占用内存。

#pragma这是个预处理指令(预处理后续会讲),可以修改编译器的默认对齐数。

结构体在对齐方式不合适的时候,我们可以自己更改默认对齐数。

2.8 结构体传参

我们在结构体传参的时候,尽量传结构体的地址,可以节约时间和空间上的传统开销。

为什么优先使用传址的方式比较节省空间和时间呢?使用传址的方式传入指针的大小不是4就是8,使用传值的方式,既要重新创建一个结构体变量空间又很可能大于8。

如果说你能思考到使用传址可能不小心将结构体的数据修改,我们可以使用const来约束指针。

3. 结构体实现位端

位段是结构体中小众但是比较使用的一个技巧。

3.1 什么是位段

我们来看一下位段的实际形态:

位段中的_只是一种命名习惯,没有说位段一定要用_,位段中的“位”指的是bit位,位段后面的数字指的就是成员变量占的bit位,可以看到使用位段的方式大大减少了使用空间,这时候聪明的你,肯定会想到位段中的总共也就47个bit位啊,为什么占了8个字节?

位段依托的是基础容器,一个位段容器不能成员不能跨越两个容器,空间不够就再开一个容器,刚开始时,一个int容器32个bit位,_a+_b+_c=17个bit位,不够再将_d也装上,所以说这时候我们就要再开一个int容器来存放_d,2个int容器也就是8个字节空间。

这时候聪明的你就可能有疑问,那位段会不会里面的类型都一样?并不是的,位段允许混合不同类型的位段成员,但是有一条关键规则相邻、同类型的位段,才会放进同一个容器;一旦类型切换,立刻开启新容器。

3.2 位段的内存分配

位段有很多的不确定因素,如果是跨平台最好不要使用位段

3.3 位段的注意事项

位段中的成员可能没有地址,我们前面三个成员变量存放到一个容器中,_d放不下就重新开辟一个容器,但是前一个容器是还有空间的,如果整个字节的起始地址就是那个没有使用的空间,那存放到里面的成员是不是就没有地址,所以我们不能使用&来获取地址。

4. 总结

结构体是自定义类型中的一个重要模块,也是干货最多的,后续还有其他的自定义类型,例如联合和枚举,本文文章篇幅较长,希望看到这里的各位能有所收获。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/17 19:53:52

免客户端一键获取直链:一个脚本打通8大网盘极速下载

免客户端一键获取直链:一个脚本打通8大网盘极速下载 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云…

作者头像 李华
网站建设 2026/8/17 19:49:54

Foxmail未读状态异常排查与修复指南

1. 问题现象与初步排查Foxmail作为国内广泛使用的邮件客户端,未读状态显示异常是许多用户遇到的典型问题。当收件箱中的邮件始终显示未读状态(红色未读标记不消失),通常表现为以下几种情况:点击邮件后状态未更新已读标…

作者头像 李华
网站建设 2026/8/17 19:49:30

Unlock-Music音乐解锁完整指南:免费在浏览器搞定20+种加密格式

Unlock-Music音乐解锁完整指南:免费在浏览器搞定20种加密格式 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库: 1. https://github.com/unlock-music/unlock-music ;2. https://git.unlock-music.dev/um/web 项目地址…

作者头像 李华
网站建设 2026/8/17 19:48:48

【单片机课设毕设项目】基于 STM32 的定时模式健康指标监测设备设计与实现 基于 STM32 的轻量化人体运动健康安全监测系统开发(013303)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

作者头像 李华
网站建设 2026/8/17 19:45:26

每日英语-12

1.overcome an obstacle 克服障碍 hit an obstacle 播上障碍物 an obstacle to sth 对 的障碍2.hack vi.vt.剪,砍;非法侵入(计算机) hijack vt.劫持(门飞机、车辆等);控制,操纵hijack a plane 机 hijacka car劫车 hijack a campaign 操纵选举3.glan…

作者头像 李华