恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

C结构体基础(二)

  • 首页
  • 资讯中心
  • /
  • C结构体基础(二)

相关资讯

SiliconCloud智能体开发:Claude Code接入TaoToken的配置与验证 2026/10/8 22:12:34
趣博思 AI|排版不是美化修饰,是论文学术规范的底层骨架 2026/10/8 22:12:34
C#操控SolidWorks图纸标注:环境搭建到批量自动化实战 2026/10/8 22:07:34

最新资讯

Hyperframes超帧技术:实现高质量视频插帧与慢动作重建
minisip-0.7.0源码编译与SIP对接实战:从注册到呼叫的避坑指南
电钢琴和真钢琴怎么选?从声学结构和硬件成本分析
缝制工厂招工难?自动化改造把“靠人“变成“靠参数“
JavaWeb旅游管理系统:JSP+Servlet+MySQL毕设实战
SSH 常见用法(二):通过 SSH 认证访问 Git 仓库

今日推荐

context-mode实战指南:从全量塞入到结构化裁剪与检索增强
大模型对话上下文管理实战:三种模式与Token优化
抖音用户主页视频数据爬虫详解:点赞、收藏、分享字段抓取与 TaoToken 统一 Key 配置

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

C结构体基础(二)

发布时间:2026/10/8 22:12:34
C结构体基础(二) C结构体基础二结构体数组结构体指针指向结构体数组的指针结构体作为函数参数1. 结构体作为函数参数2. 结构体数组的动态分配与扩容结构体数组一个结构体变量可以保存一个学生的多项信息这些信息可以具有不同的数据类型同一个结构体类型又可以定义出多个结构体变量用来保存不同学生的信息。数组正好适合存放相同类型的数据因此可以把这些同类型的结构体变量组织到一个数组中从而实现对多个学生信息的统一管理而不是零散地逐个处理。这里我们引出结构体数组。简单来讲结构体数组就是以结构体类型作为元素类型的数组数组中的每一个元素都是一个结构体变量。例如struct Student students[3];就定义了一个包含 3 个Student结构体变量的数组可以通过students[0]、students[1]、students[2]分别访问这些结构体变量再使用.运算符访问其中的成员。这可以作为一道结构体数组的练习题给定 n 名学生每名学生包含姓名和成绩两个信息请输出成绩最高的学生姓名和成绩。参考示例#includestdio.hstructStudent{charname[50];intscore;};intmain(){intn,max,j0;scanf(%d,n);structStudentstus[n];for(inti0;in;i){scanf(%s,stus[i].name);scanf(%d,stus[i].score);}maxstus[0].score;for(inti0;in;i){if(stus[i].scoremax){ji;maxstus[i].score;}}printf(name:%s score:%d,stus[j].name,max);return0;}下面结合这个例子简要梳理结构体数组的核心操作定义结构体类型Student中保留姓名name和成绩score两个成员。创建结构体数组struct Student stus[n];定义一个长度为n的数组stus[0]到stus[n-1]每个元素都是结构体变量。输入数据循环中使用stus[i].name、stus[i].score分别访问第i个学生的姓名和成绩。查找最高分遍历数组通过stus[i].score比较成绩记录最高分及对应下标。输出结果最后用stus[j].name和max输出最高分学生信息。可见操作结构体数组的关键是先定位到数组元素再用.访问其中的成员。同时也可以这样写#includestdio.hstructStudent{charname[50];intscore;};intmain(){intn,max,j0;scanf(%d,n);structStudentstus[n];for(inti0;in;i){structStudentstu;scanf(%s,stu.name);scanf(%d,stu.score);stus[i]stu;}maxstus[0].score;for(inti0;in;i){structStudentstustus[i];intScorestu.score;if(Scoremax){ji;maxScore;}}printf(name:%s score:%d,stus[j].name,max);return0;}第二种写法与第一种功能相同区别在于第一种直接访问stus[i].score进行比较第二种先通过struct Student stu stus[i];把数组元素整体赋给临时结构体变量再取出stu.score存入普通变量Score后比较。它借助了同类型结构体变量可以整体赋值的特性体现了“先取出当前元素再单独处理成员”的不同思路。结构体指针所谓结构体指针就是指向结构体变量的指针。前面我们讲过结构体变量和成员都可以取地址既然可以取地址自然也就可以定义一个指针来保存这块地址。把取出的地址交给结构体指针就可以通过这个指针间接访问结构体变量及其成员。定义结构体指针的方式与普通指针类似。例如先定义一个Student变量再定义一个指向它的指针structStudentstu;structStudent*pstu;这里p就是一个结构体指针它保存的是结构体变量stu的地址。有了结构体指针之后访问成员时通常使用-运算符p-id20260101;strcpy(p-name,张三);p-score125.5;p-id等价于(*p).id意思是先从指针p回到它所指向的结构体变量再访问其中的id成员。两者功能相同但-的写法更简洁、更常用。简单区分一下结构体变量访问成员使用.结构体指针访问成员使用-。例如假设已经定义好struct Student stu;和struct Student *p stu;那么下面的写法都是合法的stu.id20260101;// 通过结构体变量 stu 直接访问成员p-id20260102;// 通过结构体指针 p 间接访问成员(*p).id20260103;// 先解引用指针再访问成员其中stu.id是“结构体变量名 . 成员名”表示通过变量stu直接访问它里面的id成员。p-id是“结构体指针 - 成员名”表示通过指针p间接访问它指向的那个结构体的id成员。它等价于(*p).id(*p)表示先取出指针p所指向的结构体变量然后再用.访问成员。需要注意的是使用-前指针p必须已经指向一个有效的结构体变量如果指针没有初始化直接写p-id就会发生错误。指向结构体数组的指针前面我们学习的结构体指针通常用于指向一个单独的结构体变量。其实结构体指针也可以指向结构体数组用来保存结构体数组中某个元素的地址。由于数组名本身表示数组首元素的地址因此结构体数组与结构体指针可以很好地配合使用。下面的例子先用下标方式遍历结构体数组这是最常规的写法。#includestdio.hstructStudent{charname[10];intscore;}stus[3]{{张三,120},{李四,125},{王五,115}};intmain(){for(inti0;i3;i){printf(姓名%s分数%d\n,stus[i].name,stus[i].score);}return0;}那么能不能改用指针来实现同样的遍历功能呢答案是可以的。下面先看一种初学者较容易理解的写法。初学者写法先通过下标i找到当前元素再用p stus[i];让指针指向它。#includestdio.hstructStudent{charname[10];intscore;}stus[3]{{张三,120},{李四,125},{王五,115}};intmain(){structStudent*p;for(inti0;i3;i){pstus[i];printf(姓名%s分数%d\n,p-name,(*p).score);}return0;}更简洁的写法直接让指针从数组首地址开始向后移动一次访问一个元素。#includestdio.hstructStudent{charname[10];intscore;}stus[3]{{张三,120},{李四,125},{王五,115}};intmain(){for(structStudent*pstus;pstus3;p){printf(姓名%s分数%d\n,p-name,(*p).score);}return0;}观察三种写法可以发现它们的输出结果完全相同区别只在于访问数组元素的方式。第一种使用下标stus[i]第二种先把下标对应的地址交给指针p再通过p-name、(*p).score间接访问第三种则直接利用“数组名是首元素地址”这一特点让指针p从stus开始逐步后移直到遍历完所有元素。其中p并不是让地址简单地加1而是按一个struct Student元素的大小向后移动一格这正体现了结构体数组在内存中连续存放的特点。相比前两种写法第三种不需要额外维护下标使用指针遍历结构体数组时更简洁、更常用。结构体作为函数参数结构体变量和结构体变量的指针都可以作为函数参数。当形参是结构体变量时函数内部得到的是实参的一份副本修改副本不会影响原数据当形参是结构体指针或结构体数组名时函数内部通过地址直接操作原数据既可以修改实参又避免复制整个结构体。下面以一个学生管理系统为例重点讲解结构体作为参数传入以及结构体数组的动态内存分配。#includestdio.h#includestdlib.hintupSize(intsize){if(size0){size;}returnsize;}intcheckIndex(intsize0){intindex;do{printf(请输入一个编号0~%d\n,size0-1);intindex;scanf(%d,index);if(index0||indexsize0-1){printf(输入的编号不存在请重新输入\n);}else{returnindex;}}while(1);}structStudent{charname[50];charstuID[50];intage;intscore;};voidshowInfo(structStudentstu){printf(【姓名%s 学号%s 学分%d 年龄%d】\n,stu.name,stu.stuID,stu.score,stu.age);}structStudent*addStu(int*size,structStudentstuList[],int*len){printf( 请输入姓名 学号 学分 年龄\n);structStudentstu;scanf(%s,stu.name);scanf(%s,stu.stuID);scanf(%d,stu.score);scanf(%d,stu.age);if(*size*len){intnewLen*len*2;structStudent*newStuList(structStudent*)malloc(sizeof(structStudent)*newLen);for(inti0;i*size;i){newStuList[i]stuList[i];}*lennewLen;stuListnewStuList;printf(扩容完成当前的总容量升级为%d\n,*len);}stuList[*size]stu;*size*size1;returnstuList;}voidremoveStu(intsize0,structStudent*stuList,int*size){intncheckIndex(size0);structStudentoldStustuList[n];for(intin;i*size-n;i){stuList[i]stuList[i1];}*size*size-1;printf(学生管理系统已删除%d号位%s的所有信息\n,n,oldStu.name);}voidfindStu(intsize0,structStudentstuList[]){intncheckIndex(size0);printf(学生管理系统的%d号位储存的学生信息\n,n);structStudentstustuList[n];showInfo(stu);}intmaxAge(structStudentstuList[],intsize){structStudentstustuList[0];intn0,maxstu.age;for(inti0;isize;i){structStudentstustuList[i];if(stu.agemax){maxstu.age;ni;}}returnn;}intmaxScore(structStudentstuList[],intsize){structStudentstustuList[0];intn0,maxstu.score;for(inti0;isize;i){structStudentstustuList[i];if(stu.scoremax){maxstu.score;ni;}}returnn;}intmain(){system(chcp 65001);intsize0;intlen2;intsize0;structStudent*stuList(structStudent*)malloc(sizeof(structStudent)*len);while(1){printf( 学生管理系统 \n);printf( 101: 添加学生 \n);printf( 102: 删除学生 \n);printf( 103: 查找学生 \n);printf( 104: 筛选学生 \n);printf( 105: 显示所有学生 \n);printf( 106: 退出系统 \n);printf( 请输入功能编号\n);intcid;size0upSize(size);scanf(%d,cid);if(cid101){stuListaddStu(size,stuList,len);}elseif(cid102){removeStu(size0,stuList,size);}elseif(cid103){findStu(size0,stuList);}elseif(cid104){intcid;printf(\n);printf( 201: 筛出年纪最大的学生 \n);printf( 202: 筛出学分最高的学生 \n);printf( 请输入功能编号\n);scanf(%d,cid);if(cid201){intnmaxAge(stuList,size);structStudentstustuList[n];printf(年纪最大的学生是 %s\n,stu.name);showInfo(stu);}elseif(cid202){intnmaxScore(stuList,size);structStudentstustuList[n];printf(学分最高的学生是 %s\n,stu.name);showInfo(stu);}}elseif(cid105){for(inti0;isize;i){structStudentstustuList[i];showInfo(stu);}}elseif(cid106){printf(感谢使用学生管理系统);break;}}}1. 结构体作为函数参数在上面的代码中showInfo的形参是结构体变量voidshowInfo(structStudentstu){printf(【姓名%s 学号%s 学分%d 年龄%d】\n,stu.name,stu.stuID,stu.score,stu.age);}这种方式的本质是值传递。调用showInfo(stu)时编译器会把实参stu的所有成员复制一份到形参stu中函数内部访问的是副本因此只适合输出、查看等不需要修改原数据的场景。如果结构体很大复制整个结构体会带来一定的时间和空间开销。而addStu、removeStu、maxAge、maxScore等函数的形参则是结构体指针或结构体数组structStudent*addStu(int*size,structStudentstuList[],int*len);voidremoveStu(intsize0,structStudent*stuList,int*size);其中struct Student stuList[]作为形参时编译器会把它看成struct Student *stuList本质上都是把数组首地址传给函数。函数内部通过指针修改stuList[i]修改的是主函数中的原数组因此可以实现添加、删除等会改变原数据的操作。这也是为什么addStu需要把新数组指针返回给主函数而removeStu只需通过指针修改数组内容、不需要返回数组。2. 结构体数组的动态分配与扩容主函数中结构体数组并不是用固定长度定义而是使用malloc动态分配intlen2;structStudent*stuList(structStudent*)malloc(sizeof(structStudent)*len);malloc(sizeof(struct Student) * len)会在堆上申请一块连续内存大小正好能放下len个Student结构体。sizeof(struct Student)用于计算一个结构体变量占用的字节数包括它所有成员以及可能存在的内存对齐。返回的void *经过强制类型转换后赋给stuList此时stuList就可以像普通数组一样使用下标访问。当元素个数达到容量上限时addStu会进行扩容if(*size*len){intnewLen*len*2;structStudent*newStuList(structStudent*)malloc(sizeof(structStudent)*newLen);for(inti0;i*size;i){newStuList[i]stuList[i];}*lennewLen;stuListnewStuList;printf(扩容完成当前的总容量升级为%d\n,*len);}扩容的思路是申请一块更大的新空间把旧数组中的元素逐个复制到新数组再让stuList指向新空间。注意动态分配的内存使用完毕后通常应使用free释放以避免内存泄漏上面的示例为了保持简洁省略了释放旧空间的步骤实际项目中应妥善管理内存。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号