尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

指针与结构体:C 语言进阶核心详解

指针与结构体:C 语言进阶核心详解 1. 引言在 C 语言的学习过程中指针与结构体是两个绕不开的核心概念。指针让我们能够直接操作内存地址而结构体则允许我们将不同类型的数据组合成一个整体。当这两者结合时便诞生了 C 语言中最强大、也最让初学者头疼的用法——结构体指针。本文将带你从基础出发逐步深入理解指针与结构体的关系掌握结构体指针的定义、初始化、访问方式以及它在链表、动态内存分配等场景中的典型应用。2. 结构体基础回顾在讨论指针之前我们先快速回顾一下结构体的基本用法。2.1 结构体的定义structStudent{charname[50];intage;floatscore;};2.2 结构体变量的声明与初始化structStudentstu1{张三,20,89.5};structStudentstu2;2.3 通过点运算符访问成员printf(姓名%s\n,stu1.name);printf(年龄%d\n,stu1.age);printf(成绩%.1f\n,stu1.score);3. 指针基础回顾指针是存储变量地址的变量。理解指针首先要理解地址与取地址运算符。3.1 指针的声明与赋值inta10;int*pa;// p 存储变量 a 的地址3.2 解引用运算符printf(%d\n,*p);// 输出 10*p 表示 p 指向的变量的值4. 结构体指针结构体指针就是指向结构体变量的指针。它存储的是结构体变量在内存中的起始地址。4.1 结构体指针的声明structStudent*pStu;4.2 结构体指针的初始化structStudentstu1{张三,20,89.5};structStudent*pStustu1;4.3 通过指针访问结构体成员访问结构体指针所指向的成员有两种方式方式一先解引用再使用点运算符(*pStu).age21;printf(年龄%d\n,(*pStu).age);方式二使用箭头运算符推荐pStu-age21;printf(年龄%d\n,pStu-age);注意pStu-age等价于(*pStu).age。箭头运算符-是 C 语言专门为结构体指针提供的语法糖书写更简洁也更不容易出错。5. 结构体指针作为函数参数将结构体指针作为函数参数传递可以避免结构体整体拷贝带来的性能开销同时允许函数直接修改原结构体的内容。5.1 传递结构体变量值传递voidprintStudent(structStudentstu){printf(姓名%s\n,stu.name);}这种方式会拷贝整个结构体当结构体很大时效率较低。5.2 传递结构体指针引用传递voidupdateStudent(structStudent*pStu){pStu-age1;// 直接修改原结构体}intmain(){structStudentstu1{张三,20,89.5};updateStudent(stu1);printf(年龄%d\n,stu1.age);// 输出 21return0;}5.3 传递 const 指针保护数据如果函数只需要读取结构体内容而不需要修改可以加上const修饰防止意外修改voidprintStudent(conststructStudent*pStu){printf(姓名%s\n,pStu-name);}6. 结构体指针与动态内存分配结构体指针最常见的应用之一就是配合malloc在堆上动态分配结构体内存。#includestdio.h#includestdlib.h#includestring.hstructStudent{charname[50];intage;};intmain(){structStudent*pStu(structStudent*)malloc(sizeof(structStudent));if(pStuNULL){printf(内存分配失败\n);return1;}strcpy(pStu-name,李四);pStu-age22;printf(姓名%s年龄%d\n,pStu-name,pStu-age);free(pStu);// 释放内存return0;}注意使用malloc分配的内存必须用free释放否则会造成内存泄漏。7. 结构体指针数组结构体指针数组即数组的每个元素都是一个指向结构体的指针。这在管理多个动态分配的结构体时非常有用。structStudent*students[3];students[0](structStudent*)malloc(sizeof(structStudent));students[1](structStudent*)malloc(sizeof(structStudent));students[2](structStudent*)malloc(sizeof(structStudent));// 使用students[0]-age20;students[1]-age21;students[2]-age22;// 释放for(inti0;i3;i){free(students[i]);}8. 结构体指针与链表链表是结构体指针最经典的应用场景。每个节点是一个结构体其中包含一个指向下一个节点的指针。structNode{intdata;structNode*next;};8.1 创建链表节点structNode*createNode(intdata){structNode*newNode(structNode*)malloc(sizeof(structNode));if(newNodeNULL){returnNULL;}newNode-datadata;newNode-nextNULL;returnnewNode;}8.2 在链表头部插入节点voidinsertAtHead(structNode**head,intdata){structNode*newNodecreateNode(data);if(newNodeNULL)return;newNode-next*head;*headnewNode;}注意这里使用了二级指针struct Node **head因为我们需要修改头指针本身的值。8.3 遍历链表voidprintList(structNode*head){structNode*currenthead;while(current!NULL){printf(%d - ,current-data);currentcurrent-next;}printf(NULL\n);}9. 常见错误与注意事项9.1 未初始化指针就使用structStudent*pStu;// 未初始化指向未知地址pStu-age20;// 错误野指针正确做法要么指向一个已存在的结构体变量要么用malloc分配内存。9.2 忘记释放内存structStudent*pStu(structStudent*)malloc(sizeof(structStudent));// 使用完后忘记 free(pStu);这会导致内存泄漏。务必在不再使用时调用free。9.3 释放后继续使用悬空指针free(pStu);pStu-age20;// 错误pStu 已成为悬空指针释放后应将指针置为NULLfree(pStu);pStuNULL;9.4 混淆-与.结构体变量用.访问成员stu.age结构体指针用-访问成员pStu-age10. 总结指针与结构体的结合是 C 语言进阶的重要里程碑。通过本文的学习我们掌握了结构体指针的声明、初始化与成员访问-运算符结构体指针作为函数参数的高效传参方式结构体指针配合malloc进行动态内存分配结构体指针数组与链表的典型应用常见错误与规避方法掌握这些内容后你就能更自如地编写高效、灵活的 C 程序为后续学习数据结构与算法打下坚实基础。
返回列表