职坐标学习 C语言自定义类型综合学习笔记这份笔记涵盖了结构体、枚举和联合体的核心概念、用法及内存布局细节特别对结构体部分进行了深度扩展。️ 结构体 (Struct)结构体是 C 语言中实现“对象”概念的基础它允许我们将不同类型的数据打包在一起形成一个“复合类型”。1. 概念速览是什么一种用户自定义的数据类型用于描述具有多个属性的实体如学生、商品、坐标点。核心价值数据封装。让代码更有组织性避免使用大量零散的变量。生活类比结构体类型档案袋模板说明里面要装什么文件。结构体变量一个具体的档案袋实例某个学生的档案。成员变量档案袋里的具体文件身份证、成绩单。2. 结构体类型的声明声明结构体就是设计一个“蓝图”告诉编译器这个新类型包含哪些数据。基本语法1struct 结构体标签名 { 2 成员列表; 3}; // 注意这里的分号不能丢成员类型多样性结构体的成员非常灵活可以是基本类型int,char,float,double等。数组如char name[20];或int scores[3];。其他结构体可以在一个结构体中嵌套另一个结构体需提前声明。指针如char *ptr;。优化写法 (typedef)为了简化代码通常配合typedef使用给结构体起一个别名这样定义变量时就不需要每次都写struct关键字了。1typedef struct Student { 2 char name[20]; 3 int age; 4} Stu; // 以后可以用 Stu 代替 struct Student 5 6// 使用 7Stu s1;3. 结构体变量的定义、初始化和成员访问有了蓝图类型我们就可以盖房子定义变量了。定义变量1struct Student s1; // 定义一个结构体变量 2struct Student arr[3]; // 定义结构体数组 3struct Student *p s1; // 定义结构体指针初始化方式逐个赋值定义后通过.运算符一个个赋值。注意如果成员是数组如name不能直接s1.name 张三必须使用strcpy(s1.name, 张三);。整体初始化定义时按顺序struct Student s {张三, 18};指定成员C99标准struct Student s {.age18, .name张三};顺序可以打乱代码可读性更高。整体赋值变量间同类型的结构体变量可以直接互相赋值s2 s1;内存会进行逐字节拷贝。成员访问结构体变量使用点运算符.。例如s1.age 18;结构体指针使用箭头运算符-。例如p-age 18;等价于(*p).age。4. 结构体传参当结构体作为函数参数时有两种主要方式性能和安全性截然不同。传参方式描述优缺点建议值传递将结构体的副本传递给函数。优函数内修改不影响原数据安全。缺若结构体很大复制过程消耗大量时间和内存低效。仅在结构体很小且需要保护数据时使用。地址传递 (指针)将结构体的地址传递给函数。优无需复制速度极快节省内存。缺函数内可以直接修改原数据有风险。强烈推荐。处理大型结构体时的标准做法。最佳实践只读场景如果你希望通过指针传递以提高效率但又不希望函数修改原数据可以使用const修饰1void PrintStudent(const struct Student *ps) { 2 // ps-age 20; // 编译器会报错保护了数据不被修改 3 printf(%s, ps-name); 4}5. 结构体的自引用这是实现复杂数据结构如链表、树的核心技术。概念在结构体内部包含一个指向自身类型的指针。正确写法1struct Node { 2 int data; // 数据域 3 struct Node *next; // 指针域指向下一个同类型的结构体 4};错误写法常见坑1struct Node { 2 int data; 3 struct Node next; // 错误这会导致无限递归定义编译器无法计算大小 4};应用场景链表通过next指针将多个节点串联起来。遍历逻辑1struct Node *current head; // 指向第一个节点 2while (current ! NULL) { 3 printf(%d , current-data); 4 current current-next; // 指针移向下一个节点 5}6. 补充结构体内存对齐虽然文档中将其列为独立章节但它直接影响结构体的大小和性能必须掌握。现象sizeof(结构体)的大小通常大于所有成员大小之和。原因CPU 读取内存时按“块”读取如 4 字节或 8 字节对齐效率最高。为了对齐编译器会在成员之间插入“填充字节”。计算规则第一个成员在偏移量为 0 的地址。其他成员要对齐到“对齐数”的整数倍地址对齐数 编译器默认值与该成员大小的较小值。结构体总大小必须是最大对齐数的整数倍。优化技巧尽量按照成员大小从大到小或从小到大排序定义可以减少内存空洞节省空间。浪费空间char a; int b; char c;(可能占用 12 字节)节省空间int b; char a; char c;(可能占用 8 字节) 枚举 (Enum)1. 概念速览是什么用于定义一组具名整数常量的数据类型。核心价值提高代码可读性和可维护性避免使用“魔术数字”。2. 基础语法定义格式1enum 枚举名 { 2 枚举值1, // 默认从0开始 3 枚举值2, // 默认递增 4 枚举值3 100 // 可手动指定值 5};特性枚举值本质是整数int。可以进行比较和运算如today 1。3. 使用场景状态/类型如星期、季节、性别。错误码如SUCCESS,FILE_NOT_FOUND。选项如颜色RED,GREEN,BLUE。 联合体 (Union)1. 概念速览是什么一种特殊的数据类型允许不同的数据类型共享同一块内存空间。核心特点共享内存所有成员共用一段内存修改一个成员会影响其他成员。大小计算联合体的大小至少是最大成员的大小需考虑内存对齐。2. 基础语法定义格式1union 联合名 { 2 类型 成员1; 3 类型 成员2; 4};3. 注意事项数据覆盖同一时刻只能存储其中一个成员的值。应用场景通常用于底层开发、硬件接口或需要节省内存且互斥数据的场景。 核心知识点速记卡知识点一句话总结注意事项结构体定义struct 名 {成员};结尾分号不能丢成员可以是任意类型。成员访问普通变量用.指针用-。指针访问时ptr-name等价于(*ptr).name。结构体传参推荐使用指针传递。值传递会复制整个结构体大结构体效率低。内存对齐空间换时间提高CPU访问效率。调整成员顺序小到大或大到小可节省空间。枚举具名的整数常量。默认从0开始本质是int可参与运算。联合体成员共享同一块内存。大小由最大成员决定修改一个会影响其他。自引用结构体包含指向自己的指针。是实现链表的基础成员必须是指针类型。⚠️ 避坑指南结构体自引用错误❌ 错误struct Node { int data; struct Node next; };无限递归编译报错✅ 正确struct Node { int data; struct Node *next; };指针大小固定联合体数据污染给union的int成员赋值后再读取char成员得到的不是转换后的值而是内存截断后的解释需谨慎使用。内存对齐误区不要以为char int char就是1416字节实际可能是 12 字节取决于对齐规则。枚举赋值虽然枚举本质是整数但建议赋值时使用枚举常量如today MONDAY而不是直接赋整数如today 1以保持代码可读性。
C语言自定义类型综合学习笔记
职坐标学习 C语言自定义类型综合学习笔记这份笔记涵盖了结构体、枚举和联合体的核心概念、用法及内存布局细节特别对结构体部分进行了深度扩展。️ 结构体 (Struct)结构体是 C 语言中实现“对象”概念的基础它允许我们将不同类型的数据打包在一起形成一个“复合类型”。1. 概念速览是什么一种用户自定义的数据类型用于描述具有多个属性的实体如学生、商品、坐标点。核心价值数据封装。让代码更有组织性避免使用大量零散的变量。生活类比结构体类型档案袋模板说明里面要装什么文件。结构体变量一个具体的档案袋实例某个学生的档案。成员变量档案袋里的具体文件身份证、成绩单。2. 结构体类型的声明声明结构体就是设计一个“蓝图”告诉编译器这个新类型包含哪些数据。基本语法1struct 结构体标签名 { 2 成员列表; 3}; // 注意这里的分号不能丢成员类型多样性结构体的成员非常灵活可以是基本类型int,char,float,double等。数组如char name[20];或int scores[3];。其他结构体可以在一个结构体中嵌套另一个结构体需提前声明。指针如char *ptr;。优化写法 (typedef)为了简化代码通常配合typedef使用给结构体起一个别名这样定义变量时就不需要每次都写struct关键字了。1typedef struct Student { 2 char name[20]; 3 int age; 4} Stu; // 以后可以用 Stu 代替 struct Student 5 6// 使用 7Stu s1;3. 结构体变量的定义、初始化和成员访问有了蓝图类型我们就可以盖房子定义变量了。定义变量1struct Student s1; // 定义一个结构体变量 2struct Student arr[3]; // 定义结构体数组 3struct Student *p s1; // 定义结构体指针初始化方式逐个赋值定义后通过.运算符一个个赋值。注意如果成员是数组如name不能直接s1.name 张三必须使用strcpy(s1.name, 张三);。整体初始化定义时按顺序struct Student s {张三, 18};指定成员C99标准struct Student s {.age18, .name张三};顺序可以打乱代码可读性更高。整体赋值变量间同类型的结构体变量可以直接互相赋值s2 s1;内存会进行逐字节拷贝。成员访问结构体变量使用点运算符.。例如s1.age 18;结构体指针使用箭头运算符-。例如p-age 18;等价于(*p).age。4. 结构体传参当结构体作为函数参数时有两种主要方式性能和安全性截然不同。传参方式描述优缺点建议值传递将结构体的副本传递给函数。优函数内修改不影响原数据安全。缺若结构体很大复制过程消耗大量时间和内存低效。仅在结构体很小且需要保护数据时使用。地址传递 (指针)将结构体的地址传递给函数。优无需复制速度极快节省内存。缺函数内可以直接修改原数据有风险。强烈推荐。处理大型结构体时的标准做法。最佳实践只读场景如果你希望通过指针传递以提高效率但又不希望函数修改原数据可以使用const修饰1void PrintStudent(const struct Student *ps) { 2 // ps-age 20; // 编译器会报错保护了数据不被修改 3 printf(%s, ps-name); 4}5. 结构体的自引用这是实现复杂数据结构如链表、树的核心技术。概念在结构体内部包含一个指向自身类型的指针。正确写法1struct Node { 2 int data; // 数据域 3 struct Node *next; // 指针域指向下一个同类型的结构体 4};错误写法常见坑1struct Node { 2 int data; 3 struct Node next; // 错误这会导致无限递归定义编译器无法计算大小 4};应用场景链表通过next指针将多个节点串联起来。遍历逻辑1struct Node *current head; // 指向第一个节点 2while (current ! NULL) { 3 printf(%d , current-data); 4 current current-next; // 指针移向下一个节点 5}6. 补充结构体内存对齐虽然文档中将其列为独立章节但它直接影响结构体的大小和性能必须掌握。现象sizeof(结构体)的大小通常大于所有成员大小之和。原因CPU 读取内存时按“块”读取如 4 字节或 8 字节对齐效率最高。为了对齐编译器会在成员之间插入“填充字节”。计算规则第一个成员在偏移量为 0 的地址。其他成员要对齐到“对齐数”的整数倍地址对齐数 编译器默认值与该成员大小的较小值。结构体总大小必须是最大对齐数的整数倍。优化技巧尽量按照成员大小从大到小或从小到大排序定义可以减少内存空洞节省空间。浪费空间char a; int b; char c;(可能占用 12 字节)节省空间int b; char a; char c;(可能占用 8 字节) 枚举 (Enum)1. 概念速览是什么用于定义一组具名整数常量的数据类型。核心价值提高代码可读性和可维护性避免使用“魔术数字”。2. 基础语法定义格式1enum 枚举名 { 2 枚举值1, // 默认从0开始 3 枚举值2, // 默认递增 4 枚举值3 100 // 可手动指定值 5};特性枚举值本质是整数int。可以进行比较和运算如today 1。3. 使用场景状态/类型如星期、季节、性别。错误码如SUCCESS,FILE_NOT_FOUND。选项如颜色RED,GREEN,BLUE。 联合体 (Union)1. 概念速览是什么一种特殊的数据类型允许不同的数据类型共享同一块内存空间。核心特点共享内存所有成员共用一段内存修改一个成员会影响其他成员。大小计算联合体的大小至少是最大成员的大小需考虑内存对齐。2. 基础语法定义格式1union 联合名 { 2 类型 成员1; 3 类型 成员2; 4};3. 注意事项数据覆盖同一时刻只能存储其中一个成员的值。应用场景通常用于底层开发、硬件接口或需要节省内存且互斥数据的场景。 核心知识点速记卡知识点一句话总结注意事项结构体定义struct 名 {成员};结尾分号不能丢成员可以是任意类型。成员访问普通变量用.指针用-。指针访问时ptr-name等价于(*ptr).name。结构体传参推荐使用指针传递。值传递会复制整个结构体大结构体效率低。内存对齐空间换时间提高CPU访问效率。调整成员顺序小到大或大到小可节省空间。枚举具名的整数常量。默认从0开始本质是int可参与运算。联合体成员共享同一块内存。大小由最大成员决定修改一个会影响其他。自引用结构体包含指向自己的指针。是实现链表的基础成员必须是指针类型。⚠️ 避坑指南结构体自引用错误❌ 错误struct Node { int data; struct Node next; };无限递归编译报错✅ 正确struct Node { int data; struct Node *next; };指针大小固定联合体数据污染给union的int成员赋值后再读取char成员得到的不是转换后的值而是内存截断后的解释需谨慎使用。内存对齐误区不要以为char int char就是1416字节实际可能是 12 字节取决于对齐规则。枚举赋值虽然枚举本质是整数但建议赋值时使用枚举常量如today MONDAY而不是直接赋整数如today 1以保持代码可读性。