在C语言中结构体和联合体是自定义数据类型的核心用于将不同类型的数据封装在一起而指针与二者的结合能极大提升数据操作的灵活性和效率。指针可以指向结构体、联合体变量也可以作为结构体的成员还能作为函数参数传递结构体/联合体的地址是处理复杂数据的重要手段。本文将围绕指针与结构体、联合体的核心关联知识点结合具体程序示例逐点拆解讲解每个知识点均配套程序段帮助大家吃透这一重点内容。一、指向结构体的指针指向结构体的指针简称结构体指针本质是一个指针变量它指向结构体变量的起始地址。通过结构体指针可以间接访问和修改结构体的所有成员是操作结构体最常用的方式之一尤其适合处理大型结构体避免拷贝开销。结构体指针的声明格式struct 结构体名 *指针名;声明后需将结构体变量的地址赋值给指针才能通过指针操作结构体成员。程序段示例#include stdio.h#include string.h// 定义结构体学生信息struct Student {char name[20]; // 姓名int age; // 年龄float score; // 成绩};int main() {// 定义并初始化结构体变量struct Student stu {张三, 18, 95.5};// 声明结构体指针并指向结构体变量stu的地址struct Student *stuPtr stu;// 通过结构体指针访问结构体成员两种方式// 方式1解引用指针 点运算符.printf(方式1访问\n);printf(姓名%s\n, (*stuPtr).name);printf(年龄%d\n, (*stuPtr).age);printf(成绩%.1f\n, (*stuPtr).score);// 方式2箭头运算符-结构体指针专用更简洁printf(\n方式2访问\n);printf(姓名%s\n, stuPtr-name);printf(年龄%d\n, stuPtr-age);printf(成绩%.1f\n, stuPtr-score);// 通过结构体指针修改结构体成员strcpy(stuPtr-name, 李四); // 修改姓名stuPtr-age 19; // 修改年龄stuPtr-score 98.0; // 修改成绩printf(\n修改后\n);printf(姓名%s年龄%d成绩%.1f\n, stu.name, stu.age, stu.score);return 0;}代码解析首先定义了Student结构体包含姓名、年龄、成绩三个成员然后定义结构体变量stu并初始化声明结构体指针stuPtr并赋值为stustu的地址。通过结构体指针访问成员有两种方式(*stuPtr).name 和 stuPtr-name二者完全等价但箭头运算符-更简洁是结构体指针访问成员的标准用法。同时通过结构体指针可以直接修改结构体成员的值修改后原结构体变量stu的内容会同步更新。二、箭头运算符 -箭头运算符-是C语言中专门为结构体指针设计的运算符用于简化结构体指针访问成员的语法。它的作用等价于“解引用指针 点运算符”即ptr-member完全等价于(*ptr).member。⚠️ 注意箭头运算符仅能用于结构体指针或联合体指针不能用于普通结构体变量普通结构体变量访问成员需使用点运算符.。下面通过程序段对比两种运算符的用法明确箭头运算符的使用场景。程序段示例#include stdio.h// 定义结构体书籍信息struct Book {char title[50]; // 书名char author[20]; // 作者float price; // 价格};int main() {// 1. 普通结构体变量使用点运算符.访问成员struct Book book1 {C语言编程, 张三, 59.9};printf(普通结构体变量访问\n);printf(书名%s作者%s价格%.1f\n, book1.title, book1.author, book1.price);// 2. 结构体指针使用箭头运算符-访问成员struct Book *bookPtr book1;printf(\n结构体指针访问\n);printf(书名%s作者%s价格%.1f\n, bookPtr-title, bookPtr-author, bookPtr-price);// 验证等价性printf(\n等价性验证\n);printf(bookPtr-price %.1f\n, bookPtr-price);printf((*bookPtr).price %.1f\n, (*bookPtr).price); // 与上面等价// 错误示范普通结构体变量不能使用箭头运算符// printf(%s, book1-title); // 编译报错request for member title in book1, which is of non-class type struct Book// 错误示范结构体指针不能直接使用点运算符需解引用// printf(%s, bookPtr.title); // 编译报错request for member title in bookPtr, which is of pointer type struct Book*return 0;}代码解析普通结构体变量book1使用点运算符.访问成员结构体指针bookPtr使用箭头运算符-访问成员二者访问的是同一个结构体的成员结果完全一致。箭头运算符的核心作用是简化语法避免频繁写“(*ptr).member”这种繁琐的表达式尤其在结构体指针频繁访问成员时能大幅提升代码可读性。三、结构体指针作为函数参数结构体指针作为函数参数本质是“传址调用”即将结构体变量的地址传入函数函数内通过结构体指针访问和修改原结构体的成员。这种方式的优势的是无需拷贝整个结构体尤其适合大型结构体节省内存开销且能直接修改原结构体的内容是处理结构体的常用编程方式。与“结构体变量作为函数参数”值传递相比结构体指针作为参数更高效、更灵活。下面通过两个程序段分别演示“读取结构体信息”和“修改结构体信息”的场景。3.1 结构体指针作为参数读取结构体信息代码解析printEmployee函数的参数是struct Employee*类型的结构体指针接收main函数中emp变量的地址。函数内通过箭头运算符访问结构体成员读取并打印员工信息由于传递的是地址无需拷贝整个结构体效率更高。3.2 结构体指针作为参数修改结构体信息代码解析updateStudent函数接收结构体指针stuPtr和新的学生信息通过结构体指针直接修改原结构体stu的成员。由于是传址调用函数内的修改会直接作用于main函数中的stu变量修改后能直接在main函数中看到更新后的结果体现了结构体指针作为参数的灵活性。四、指向结构体数组的指针结构体数组是由多个结构体变量组成的数组每个元素都是一个结构体。指向结构体数组的指针本质是一个结构体指针它指向结构体数组的首元素第一个结构体变量通过指针的移动可以遍历整个结构体数组访问和修改每个结构体元素的成员。结构体数组的数组名本质是指向数组首元素的结构体指针与普通数组名的特性一致。下面通过程序段演示指向结构体数组的指针的用法。程序段示例#include stdio.h#include string.h// 定义结构体学生信息struct Student {char name[20];int age;float score;};int main() {// 定义结构体数组并初始化3个学生struct Student stuArr[3] {{张三, 18, 95.5},{李四, 19, 92.0},{王五, 17, 88.5}};// 声明指向结构体数组的指针指向数组首元素等价于stuArrstruct Student *stuPtr stuArr[0];// 方式1通过指针移动遍历结构体数组printf(方式1指针移动遍历\n);for (int i 0; i 3; i) {printf(第%d个学生\n, i1);printf(姓名%s年龄%d成绩%.1f\n,(stuPtr i)-name, // 指针移动i个位置指向第i个元素(stuPtr i)-age,(stuPtr i)-score);}// 方式2指针自增遍历结构体数组printf(\n方式2指针自增遍历\n);stuPtr stuArr; // 重置指针指向数组首元素int index 1;while (stuPtr stuArr 3) {printf(第%d个学生\n, index);printf(姓名%s年龄%d成绩%.1f\n,stuPtr-name,stuPtr-age,stuPtr-score);stuPtr; // 指针自增指向后一个结构体元素}// 修改结构体数组元素通过指针stuPtr stuArr[1]; // 指向第二个学生strcpy(stuPtr-name, 赵六);stuPtr-score 96.5;printf(\n修改后第二个学生%s成绩%.1f\n, stuArr[1].name, stuArr[1].score);return 0;}代码解析stuArr是结构体数组包含3个Student类型的元素stuPtr是指向结构体数组的指针初始指向数组首元素stuArr[0]。通过指针移动stuPtr i或指针自增stuPtr可以遍历整个结构体数组访问每个元素的成员。指针自增时步长是一个结构体的大小即stuArr[0]的大小确保每次移动都指向一个完整的结构体元素。同时通过指针可以直接修改结构体数组中某个元素的成员修改后数组元素会同步更新。五、结构体中包含指针成员结构体的成员不仅可以是基本数据类型int、char、float等也可以是指针类型即指针成员。结构体中的指针成员可用于指向动态分配的内存、字符串、其他结构体等能极大提升结构体的灵活性尤其适合处理长度不固定的数据如字符串。⚠️ 注意结构体中的指针成员需要手动分配内存如使用malloc使用完毕后需手动释放否则会导致内存泄漏若指针成员未初始化会成为野指针引发程序异常。下面通过两个程序段演示结构体中指针成员的常用场景。5.1 结构体指针成员指向字符串动态分配内存#include stdio.h#include stdlib.h#include string.h// 定义结构体包含指针成员存储字符串struct Person {char *name; // 指针成员指向动态分配的字符串int age;};int main() {// 定义结构体变量struct Person p;p.age 20;// 为指针成员name动态分配内存长度为20p.name (char *)malloc(20 * sizeof(char));if (p.name NULL) { // 检查内存分配是否成功printf(内存分配失败\n);exit(1);}// 给指针成员指向的内存赋值字符串strcpy(p.name, 周八);// 访问结构体成员指针成员通过箭头运算符访问其指向的内容通过解引用访问printf(姓名%s年龄%d\n, p.name, p.age); // name是指针直接打印字符串// 修改指针成员指向的内容strcpy(p.name, 吴九);printf(修改后姓名%s\n, p.name);// 释放指针成员指向的动态内存避免内存泄漏free(p.name);p.name NULL; // 避免野指针return 0;}代码解析Person结构体包含一个char*类型的指针成员name和int类型的age。main函数中为name指针动态分配了20个char类型的内存用于存储字符串通过strcpy给name指向的内存赋值访问时直接使用p.name即可打印字符串printf的%s格式符会自动根据指针地址打印字符串。使用完毕后必须用free释放name指向的内存否则会导致内存泄漏。5.2 结构体指针成员指向另一个结构体结构体的指针成员还可以指向另一个结构体实现结构体的嵌套关联常用于表示复杂的关系如“学生-班级”“员工-部门”等。#include stdio.h#include string.h// 定义嵌套的结构体班级信息struct Class {char className[20]; // 班级名称int classId; // 班级ID};// 定义主结构体学生信息包含指向Class结构体的指针成员struct Student {char name[20];int age;struct Class *classPtr; // 指针成员指向Class结构体};int main() {// 定义并初始化Class结构体变量struct Class cls {高一(1)班, 101};// 定义Student结构体变量其指针成员指向clsstruct Student stu;strcpy(stu.name, 郑十);stu.age 18;stu.classPtr cls; // 指针成员指向Class结构体变量// 访问结构体成员通过指针成员访问嵌套的结构体printf(学生姓名%s\n, stu.name);printf(学生班级%s\n, stu.classPtr-className); // 箭头运算符访问嵌套结构体成员printf(班级ID%d\n, stu.classPtr-classId);// 修改嵌套结构体的成员通过指针成员strcpy(stu.classPtr-className, 高一(2)班);printf(\n修改后班级%s\n, cls.className); // 原Class变量同步修改return 0;}代码解析Student结构体的classPtr成员是一个指向Class结构体的指针通过将cls的地址赋值给classPtr实现了Student与Class结构体的关联。访问嵌套结构体的成员时需使用两次箭头运算符stu.classPtr-className即“先通过classPtr指针找到Class结构体再访问其className成员”。同时通过classPtr指针可以直接修改Class结构体的成员原cls变量会同步更新。六、指向联合体的指针联合体union与结构体类似也是一种自定义数据类型但其所有成员共享同一块内存空间内存大小为最大成员的大小同一时间只能存储一个成员的值。指向联合体的指针简称联合体指针本质是一个指针变量指向联合体变量的起始地址通过联合体指针可以访问和修改联合体的成员。联合体指针的声明格式union 联合体名 *指针名;其使用方式与结构体指针类似也可以使用箭头运算符-访问成员。下面通过程序段演示指向联合体的指针的用法同时体现联合体“成员共享内存”的特性。程序段示例#include stdio.h// 定义联合体共享内存存储不同类型的数据union Data {int num; // 整型4字节float f; // 浮点型4字节char ch; // 字符型1字节}; // 联合体大小为4字节最大成员的大小int main() {// 定义并初始化联合体变量union Data data;data.num 100; // 给整型成员赋值// 声明联合体指针指向联合体变量dataunion Data *dataPtr data;// 通过联合体指针访问成员使用箭头运算符-printf(通过指针访问整型成员%d\n, dataPtr-num);// 修改联合体成员通过指针注意修改一个成员会覆盖另一个成员的值dataPtr-f 3.14f;printf(修改浮点型成员后\n);printf(浮点型成员%.2f\n, dataPtr-f);printf(整型成员被覆盖%d\n, dataPtr-num); // 值被覆盖无意义// 访问字符型成员共享同一块内存dataPtr-ch A;printf(\n修改字符型成员后\n);printf(字符型成员%c\n, dataPtr-ch);printf(浮点型成员被覆盖%.2f\n, dataPtr-f); // 值被覆盖// 打印联合体地址和各成员地址验证共享内存printf(\n联合体地址%p\n, dataPtr);printf(num成员地址%p\n, dataPtr-num);printf(f成员地址%p\n, dataPtr-f);printf(ch成员地址%p\n, dataPtr-ch); // 所有成员地址相同return 0;}代码解析Data联合体包含三个成员int、float、char共享同一块内存大小为4字节即最大成员int和float的大小。联合体指针dataPtr指向data变量通过箭头运算符访问和修改联合体成员。需要注意的是由于成员共享内存修改一个成员的值会覆盖其他成员的值如修改f后num的值会变成无意义的数字这是联合体与结构体的核心区别。同时打印各成员的地址会发现所有成员的地址与联合体的地址完全一致验证了“共享内存”的特性。指向联合体的指针常用于“同一内存空间存储不同类型数据”的场景如数据类型转换、节省内存等。指针与结构体、联合体的结合是C语言处理复杂数据的核心手段核心要点可概括为结构体指针指向结构体变量的起始地址通过箭头运算符-访问成员简洁高效箭头运算符-是结构体/联合体指针的专用运算符等价于“解引用指针 点运算符”结构体指针作为函数参数实现传址调用避免拷贝开销可直接修改原结构体指向结构体数组的指针通过指针移动遍历数组访问每个结构体元素结构体中的指针成员可指向动态内存、字符串或其他结构体需注意内存分配与释放避免内存泄漏联合体指针与结构体指针用法类似但联合体成员共享内存同一时间只能存储一个成员的值。掌握这些知识点的关键是理解“指针的指向”和“结构体/联合体的内存布局”尤其是结构体指针成员的内存管理和联合体“共享内存”的特性多写程序、多调试才能灵活运用指针与结构体、联合体处理复杂的自定义数据。
5、C语言指针专题:指针与结构体、联合体
在C语言中结构体和联合体是自定义数据类型的核心用于将不同类型的数据封装在一起而指针与二者的结合能极大提升数据操作的灵活性和效率。指针可以指向结构体、联合体变量也可以作为结构体的成员还能作为函数参数传递结构体/联合体的地址是处理复杂数据的重要手段。本文将围绕指针与结构体、联合体的核心关联知识点结合具体程序示例逐点拆解讲解每个知识点均配套程序段帮助大家吃透这一重点内容。一、指向结构体的指针指向结构体的指针简称结构体指针本质是一个指针变量它指向结构体变量的起始地址。通过结构体指针可以间接访问和修改结构体的所有成员是操作结构体最常用的方式之一尤其适合处理大型结构体避免拷贝开销。结构体指针的声明格式struct 结构体名 *指针名;声明后需将结构体变量的地址赋值给指针才能通过指针操作结构体成员。程序段示例#include stdio.h#include string.h// 定义结构体学生信息struct Student {char name[20]; // 姓名int age; // 年龄float score; // 成绩};int main() {// 定义并初始化结构体变量struct Student stu {张三, 18, 95.5};// 声明结构体指针并指向结构体变量stu的地址struct Student *stuPtr stu;// 通过结构体指针访问结构体成员两种方式// 方式1解引用指针 点运算符.printf(方式1访问\n);printf(姓名%s\n, (*stuPtr).name);printf(年龄%d\n, (*stuPtr).age);printf(成绩%.1f\n, (*stuPtr).score);// 方式2箭头运算符-结构体指针专用更简洁printf(\n方式2访问\n);printf(姓名%s\n, stuPtr-name);printf(年龄%d\n, stuPtr-age);printf(成绩%.1f\n, stuPtr-score);// 通过结构体指针修改结构体成员strcpy(stuPtr-name, 李四); // 修改姓名stuPtr-age 19; // 修改年龄stuPtr-score 98.0; // 修改成绩printf(\n修改后\n);printf(姓名%s年龄%d成绩%.1f\n, stu.name, stu.age, stu.score);return 0;}代码解析首先定义了Student结构体包含姓名、年龄、成绩三个成员然后定义结构体变量stu并初始化声明结构体指针stuPtr并赋值为stustu的地址。通过结构体指针访问成员有两种方式(*stuPtr).name 和 stuPtr-name二者完全等价但箭头运算符-更简洁是结构体指针访问成员的标准用法。同时通过结构体指针可以直接修改结构体成员的值修改后原结构体变量stu的内容会同步更新。二、箭头运算符 -箭头运算符-是C语言中专门为结构体指针设计的运算符用于简化结构体指针访问成员的语法。它的作用等价于“解引用指针 点运算符”即ptr-member完全等价于(*ptr).member。⚠️ 注意箭头运算符仅能用于结构体指针或联合体指针不能用于普通结构体变量普通结构体变量访问成员需使用点运算符.。下面通过程序段对比两种运算符的用法明确箭头运算符的使用场景。程序段示例#include stdio.h// 定义结构体书籍信息struct Book {char title[50]; // 书名char author[20]; // 作者float price; // 价格};int main() {// 1. 普通结构体变量使用点运算符.访问成员struct Book book1 {C语言编程, 张三, 59.9};printf(普通结构体变量访问\n);printf(书名%s作者%s价格%.1f\n, book1.title, book1.author, book1.price);// 2. 结构体指针使用箭头运算符-访问成员struct Book *bookPtr book1;printf(\n结构体指针访问\n);printf(书名%s作者%s价格%.1f\n, bookPtr-title, bookPtr-author, bookPtr-price);// 验证等价性printf(\n等价性验证\n);printf(bookPtr-price %.1f\n, bookPtr-price);printf((*bookPtr).price %.1f\n, (*bookPtr).price); // 与上面等价// 错误示范普通结构体变量不能使用箭头运算符// printf(%s, book1-title); // 编译报错request for member title in book1, which is of non-class type struct Book// 错误示范结构体指针不能直接使用点运算符需解引用// printf(%s, bookPtr.title); // 编译报错request for member title in bookPtr, which is of pointer type struct Book*return 0;}代码解析普通结构体变量book1使用点运算符.访问成员结构体指针bookPtr使用箭头运算符-访问成员二者访问的是同一个结构体的成员结果完全一致。箭头运算符的核心作用是简化语法避免频繁写“(*ptr).member”这种繁琐的表达式尤其在结构体指针频繁访问成员时能大幅提升代码可读性。三、结构体指针作为函数参数结构体指针作为函数参数本质是“传址调用”即将结构体变量的地址传入函数函数内通过结构体指针访问和修改原结构体的成员。这种方式的优势的是无需拷贝整个结构体尤其适合大型结构体节省内存开销且能直接修改原结构体的内容是处理结构体的常用编程方式。与“结构体变量作为函数参数”值传递相比结构体指针作为参数更高效、更灵活。下面通过两个程序段分别演示“读取结构体信息”和“修改结构体信息”的场景。3.1 结构体指针作为参数读取结构体信息代码解析printEmployee函数的参数是struct Employee*类型的结构体指针接收main函数中emp变量的地址。函数内通过箭头运算符访问结构体成员读取并打印员工信息由于传递的是地址无需拷贝整个结构体效率更高。3.2 结构体指针作为参数修改结构体信息代码解析updateStudent函数接收结构体指针stuPtr和新的学生信息通过结构体指针直接修改原结构体stu的成员。由于是传址调用函数内的修改会直接作用于main函数中的stu变量修改后能直接在main函数中看到更新后的结果体现了结构体指针作为参数的灵活性。四、指向结构体数组的指针结构体数组是由多个结构体变量组成的数组每个元素都是一个结构体。指向结构体数组的指针本质是一个结构体指针它指向结构体数组的首元素第一个结构体变量通过指针的移动可以遍历整个结构体数组访问和修改每个结构体元素的成员。结构体数组的数组名本质是指向数组首元素的结构体指针与普通数组名的特性一致。下面通过程序段演示指向结构体数组的指针的用法。程序段示例#include stdio.h#include string.h// 定义结构体学生信息struct Student {char name[20];int age;float score;};int main() {// 定义结构体数组并初始化3个学生struct Student stuArr[3] {{张三, 18, 95.5},{李四, 19, 92.0},{王五, 17, 88.5}};// 声明指向结构体数组的指针指向数组首元素等价于stuArrstruct Student *stuPtr stuArr[0];// 方式1通过指针移动遍历结构体数组printf(方式1指针移动遍历\n);for (int i 0; i 3; i) {printf(第%d个学生\n, i1);printf(姓名%s年龄%d成绩%.1f\n,(stuPtr i)-name, // 指针移动i个位置指向第i个元素(stuPtr i)-age,(stuPtr i)-score);}// 方式2指针自增遍历结构体数组printf(\n方式2指针自增遍历\n);stuPtr stuArr; // 重置指针指向数组首元素int index 1;while (stuPtr stuArr 3) {printf(第%d个学生\n, index);printf(姓名%s年龄%d成绩%.1f\n,stuPtr-name,stuPtr-age,stuPtr-score);stuPtr; // 指针自增指向后一个结构体元素}// 修改结构体数组元素通过指针stuPtr stuArr[1]; // 指向第二个学生strcpy(stuPtr-name, 赵六);stuPtr-score 96.5;printf(\n修改后第二个学生%s成绩%.1f\n, stuArr[1].name, stuArr[1].score);return 0;}代码解析stuArr是结构体数组包含3个Student类型的元素stuPtr是指向结构体数组的指针初始指向数组首元素stuArr[0]。通过指针移动stuPtr i或指针自增stuPtr可以遍历整个结构体数组访问每个元素的成员。指针自增时步长是一个结构体的大小即stuArr[0]的大小确保每次移动都指向一个完整的结构体元素。同时通过指针可以直接修改结构体数组中某个元素的成员修改后数组元素会同步更新。五、结构体中包含指针成员结构体的成员不仅可以是基本数据类型int、char、float等也可以是指针类型即指针成员。结构体中的指针成员可用于指向动态分配的内存、字符串、其他结构体等能极大提升结构体的灵活性尤其适合处理长度不固定的数据如字符串。⚠️ 注意结构体中的指针成员需要手动分配内存如使用malloc使用完毕后需手动释放否则会导致内存泄漏若指针成员未初始化会成为野指针引发程序异常。下面通过两个程序段演示结构体中指针成员的常用场景。5.1 结构体指针成员指向字符串动态分配内存#include stdio.h#include stdlib.h#include string.h// 定义结构体包含指针成员存储字符串struct Person {char *name; // 指针成员指向动态分配的字符串int age;};int main() {// 定义结构体变量struct Person p;p.age 20;// 为指针成员name动态分配内存长度为20p.name (char *)malloc(20 * sizeof(char));if (p.name NULL) { // 检查内存分配是否成功printf(内存分配失败\n);exit(1);}// 给指针成员指向的内存赋值字符串strcpy(p.name, 周八);// 访问结构体成员指针成员通过箭头运算符访问其指向的内容通过解引用访问printf(姓名%s年龄%d\n, p.name, p.age); // name是指针直接打印字符串// 修改指针成员指向的内容strcpy(p.name, 吴九);printf(修改后姓名%s\n, p.name);// 释放指针成员指向的动态内存避免内存泄漏free(p.name);p.name NULL; // 避免野指针return 0;}代码解析Person结构体包含一个char*类型的指针成员name和int类型的age。main函数中为name指针动态分配了20个char类型的内存用于存储字符串通过strcpy给name指向的内存赋值访问时直接使用p.name即可打印字符串printf的%s格式符会自动根据指针地址打印字符串。使用完毕后必须用free释放name指向的内存否则会导致内存泄漏。5.2 结构体指针成员指向另一个结构体结构体的指针成员还可以指向另一个结构体实现结构体的嵌套关联常用于表示复杂的关系如“学生-班级”“员工-部门”等。#include stdio.h#include string.h// 定义嵌套的结构体班级信息struct Class {char className[20]; // 班级名称int classId; // 班级ID};// 定义主结构体学生信息包含指向Class结构体的指针成员struct Student {char name[20];int age;struct Class *classPtr; // 指针成员指向Class结构体};int main() {// 定义并初始化Class结构体变量struct Class cls {高一(1)班, 101};// 定义Student结构体变量其指针成员指向clsstruct Student stu;strcpy(stu.name, 郑十);stu.age 18;stu.classPtr cls; // 指针成员指向Class结构体变量// 访问结构体成员通过指针成员访问嵌套的结构体printf(学生姓名%s\n, stu.name);printf(学生班级%s\n, stu.classPtr-className); // 箭头运算符访问嵌套结构体成员printf(班级ID%d\n, stu.classPtr-classId);// 修改嵌套结构体的成员通过指针成员strcpy(stu.classPtr-className, 高一(2)班);printf(\n修改后班级%s\n, cls.className); // 原Class变量同步修改return 0;}代码解析Student结构体的classPtr成员是一个指向Class结构体的指针通过将cls的地址赋值给classPtr实现了Student与Class结构体的关联。访问嵌套结构体的成员时需使用两次箭头运算符stu.classPtr-className即“先通过classPtr指针找到Class结构体再访问其className成员”。同时通过classPtr指针可以直接修改Class结构体的成员原cls变量会同步更新。六、指向联合体的指针联合体union与结构体类似也是一种自定义数据类型但其所有成员共享同一块内存空间内存大小为最大成员的大小同一时间只能存储一个成员的值。指向联合体的指针简称联合体指针本质是一个指针变量指向联合体变量的起始地址通过联合体指针可以访问和修改联合体的成员。联合体指针的声明格式union 联合体名 *指针名;其使用方式与结构体指针类似也可以使用箭头运算符-访问成员。下面通过程序段演示指向联合体的指针的用法同时体现联合体“成员共享内存”的特性。程序段示例#include stdio.h// 定义联合体共享内存存储不同类型的数据union Data {int num; // 整型4字节float f; // 浮点型4字节char ch; // 字符型1字节}; // 联合体大小为4字节最大成员的大小int main() {// 定义并初始化联合体变量union Data data;data.num 100; // 给整型成员赋值// 声明联合体指针指向联合体变量dataunion Data *dataPtr data;// 通过联合体指针访问成员使用箭头运算符-printf(通过指针访问整型成员%d\n, dataPtr-num);// 修改联合体成员通过指针注意修改一个成员会覆盖另一个成员的值dataPtr-f 3.14f;printf(修改浮点型成员后\n);printf(浮点型成员%.2f\n, dataPtr-f);printf(整型成员被覆盖%d\n, dataPtr-num); // 值被覆盖无意义// 访问字符型成员共享同一块内存dataPtr-ch A;printf(\n修改字符型成员后\n);printf(字符型成员%c\n, dataPtr-ch);printf(浮点型成员被覆盖%.2f\n, dataPtr-f); // 值被覆盖// 打印联合体地址和各成员地址验证共享内存printf(\n联合体地址%p\n, dataPtr);printf(num成员地址%p\n, dataPtr-num);printf(f成员地址%p\n, dataPtr-f);printf(ch成员地址%p\n, dataPtr-ch); // 所有成员地址相同return 0;}代码解析Data联合体包含三个成员int、float、char共享同一块内存大小为4字节即最大成员int和float的大小。联合体指针dataPtr指向data变量通过箭头运算符访问和修改联合体成员。需要注意的是由于成员共享内存修改一个成员的值会覆盖其他成员的值如修改f后num的值会变成无意义的数字这是联合体与结构体的核心区别。同时打印各成员的地址会发现所有成员的地址与联合体的地址完全一致验证了“共享内存”的特性。指向联合体的指针常用于“同一内存空间存储不同类型数据”的场景如数据类型转换、节省内存等。指针与结构体、联合体的结合是C语言处理复杂数据的核心手段核心要点可概括为结构体指针指向结构体变量的起始地址通过箭头运算符-访问成员简洁高效箭头运算符-是结构体/联合体指针的专用运算符等价于“解引用指针 点运算符”结构体指针作为函数参数实现传址调用避免拷贝开销可直接修改原结构体指向结构体数组的指针通过指针移动遍历数组访问每个结构体元素结构体中的指针成员可指向动态内存、字符串或其他结构体需注意内存分配与释放避免内存泄漏联合体指针与结构体指针用法类似但联合体成员共享内存同一时间只能存储一个成员的值。掌握这些知识点的关键是理解“指针的指向”和“结构体/联合体的内存布局”尤其是结构体指针成员的内存管理和联合体“共享内存”的特性多写程序、多调试才能灵活运用指针与结构体、联合体处理复杂的自定义数据。