ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

C语言学习--结构体

2026/8/25 14:09:38 拓冰建站 浏览量
C语言学习--结构体 结构体C 语言内置的数据类型除了几种原始的基本数据类型只有数组属于复合类型可以同时包含多个值但是只能包含相同类型的数据实际使用场景受限。什么是结构体C语言提供了struct关键字允许自定义复合数据类型将不同类型的值组合在一起这种类型称为结构体structure类型。C语言没有其他语言的对象object和类class的概念struct 结构很大程度上提供了对象和类的功能。声明结构体struct 类型名称{成员类型 成员名称;成员类型 成员名称;成员类型 成员名称;成员类型 成员名称;成员类型 成员名称;....}注意类型名称和成员名称都需要符合标识符规范结构体的成员类型可以是任意类型整数、浮点、数组、指针、枚举、结构体声明结构体变量1.先定义结构体然后再创建结构体变量//定义结构体structStudent{intid;//学号intage;//年龄char*name;//姓名chargender;//性别char*address;//家庭住址};//定义结构体变量structStudent stu1,stu2;2.在定义结构体的同时定义结构体变量//定义结构体的同时定义stu1和stu2两个变量structStudent{intid;//学号intage;//年龄char*name;//姓名chargender;//性别char*address;//家庭住址}stu1,stu2;3. 在定义时也可以不给出结构体名//不给出结构体的名字struct{intid;//学号intage;//年龄char*name;//姓名chargender;//性别char*address;//家庭住址}stu1,stu2;注意在C语言中结构体struct和结构体变量是两个不同的概念。结构体是一种自定义的数据类型像一种模板定义了数据的格式。结构体变量是根据结构体类型创建的变量代表了一个具体的对象用于存储数据。结构体变量初始化赋值第一种方式先定义结构体变量依次给成员赋值第二种方式定义结构体变量同时使用大括号给成员赋值结构体变量访问结构体成员使用 . 运算符代码案例#include stdio.h #include string.h // 定义结构体类型 描述学生信息(学号、姓名、性别、年龄、成绩、地址) struct Student { int id; char *name; enum { MALE, FEMALE, ELSE } gender; int age; double grade; char address[40]; }; // 定义函数 打印学生信息 void printStuInfo(struct Student stu) { char *gender NULL; switch (stu.gender) { case MALE: gender 男; break; case FEMALE: gender 女; break; case ELSE: gender 其他; break; } // 打印 printf(学号:%d, 姓名:%s, 性别:%s, 年龄:%d, 成绩:%.2lf, 地址:%s \n, stu.id, stu.name, gender, stu.age, stu.grade, stu.address); } int main() { // 根据结构体类型定义结构体变量 struct Student stu1; // 先定义结构体变量对成员挨个初始化赋值 使用 . 运算符 stu1.id 1001; stu1.name 曹操; stu1.gender MALE; stu1.grade 28; stu1.age 48; // stu1.address 上海; // 错误 strcpy(stu1.address, 上海); // 定义结构体变量并初始化赋值 struct Student stu2 {1002, 刘备, ELSE, 45, 98, 成都}; // 打印学生信息 printStuInfo(stu1); printStuInfo(stu2); return 0; }代码中的主要内容还是如何声明结构体如何定义结构体变量。最使用的还是定义结构体变量并同时初始化赋值。数组元素是结构体类型// 定义数组数组元素都是 struct Student 类型 struct Student stus[3] { {1003, 关羽, ELSE, 45, 98, 成都}, {1004, 张飞, ELSE, 45, 98, 成都}, {1005, 孙权, FEMALE, 25, 18, 南京}}; // 遍历并打印数组信息 for (int i 0; i 3; i) { printStuInfo(stus[i]); }结构体指针结构体指针介绍结构体指针是指向结构体的指针变量允许间接访问和操作结构体的成员它提供了一种方便的方式来处理结构体数据。声明结构体指针的语法格式struct结构体名*结构体指针变量名;声明结构体指针通常需要先定义一个结构体变量再创建结构体指针并取结构体变量的地址作为结构体指针的值。//声明结构体structStudent{intid;//学号intage;//年龄char*name;//姓名chargender;//性别char*address;//家庭住址};//声明结构体变量structStudentstu;//声明结构体指针并初始化structStudent*ptrstu;通过结构体指针访问成员结构体指针可以通过“-” 操作符访问结构体的成员。#includestdio.hintmain(){//结构体structStudent{char*name;intage;chargender;};//结构体变量structStudents{张三,20,M};//通过结构体变量访问成员printf(name%s,age%d,gender%c\n,s.name,s.age,s.gender);//声明结构体指针structStudent*pss;//结构体指针通过解引用访问成员printf(name%s,age%d,gender%c\n, (*ps).name, (*ps).age, (*ps).gender);//结构体指针使用-访问成员printf(name%s,age%d,gender%c\n,ps-name,ps-age,ps-gender);return0;}输出结果name张三,age20,genderMname张三,age20,genderMname张三,age20,genderM总结如果指针变量p指向一个结构体变量stu以下3种用法等价stu.成员名(*p).成员名p-成员名 本质就是(*p).成员名代码案例#include stdio.h #include string.h // 定义结构体类型 描述学生信息(学号、姓名、性别、年龄、成绩、地址) struct Student { int id; // 学号 char *name; // 姓名 enum { MALE, FEMALE, ELSE } gender; // 性别 int age; // 年龄 double score; // 成绩 char address[40]; // 地址 }; // 定义函数 打印学生信息 void printStuInfo(struct Student stu) { // 处理性别信息 char *gender NULL; switch (stu.gender) { case MALE: gender 男; break; case FEMALE: gender 女; break; case ELSE: gender 其他; break; } // 打印 printf(学号:%d, 姓名:%s, 性别:%s, 年龄:%d, 成绩:%.2lf, 地址:%s \n, stu.id, stu.name, gender, stu.age, stu.score, stu.address); } // 定义函数让年龄增长 void addStuAge(struct Student *stu) { stu-age; //等于 (*stu).age; } int main() { // 定义结构体变量并初始化赋值 struct Student stu {1002, 刘备, ELSE, 45, 98, 成都}; // 定义结构体指针指向 stu struct Student *stu_ptr stu; // 使用结构体指针 printf(姓名%s \n, stu.name); printf(姓名%s \n, (*stu_ptr).name); printf(姓名%s \n, stu_ptr-name); // -是语法糖 *(stu_ptr).name // 调用函数 addStuAge(stu); addStuAge(stu_ptr); // 打印 printStuInfo(stu); return 0; }结构体指针用处就跟其他指针的用处是一样的在自定义函数中的值传递和地址传递的区别。结构体应用案例1一个景区根据游人的年龄收取不同价格的门票。2请编写游客结构体Visitor根据年龄段决定能够购买的门票价格并输出。3规则年龄18门票为20元其它情况免费。4可以循环从控制台输入名字\年龄\性别打印信息“尊敬的XXX先生/女士您需要支付XX元”如果名字输入n则退出程序。#include stdio.h #include string.h struct Visitor { char name[20]; enum { MALE, FEMALE } gender; int age; }; int main() { while (1) { struct Visitor visitor; printf(请输入游客的姓名——————————————\n); printf(姓名:); scanf(%s, visitor.name); if (visitor.name[0] n strlen(visitor.name) 1) { break; } printf(请选择性别:(男:0, 女:1)); scanf(%d, (int *)visitor.gender); printf(年龄:); scanf(%d, visitor.age); printf(尊敬的%s %s您需要支付%d元 \n\n, visitor.name, visitor.gender FEMALE ? 女士 : 先生, visitor.age 18 ? 20 : 0); } printf(退出\n); return 0; }必须使用字符数组而非字符指针来存储字符串因为字符指针没有分配内存空间会导致运行时错误。虽然某些系统可能偶尔能正常运行但这是不确定的行为。内存分配原理字符指针无法获取用户输入是因为没有指向有效内存空间即使指向字符串常量也不行常量不可修改。结构体存储大小的计算规则成员偏移位置对齐每个成员的偏移位置一定是自身大小的整数倍如果成员比基准对齐长度大按照基准对齐长度偏移。结构体整体对齐结构体的总大小一定是基准对齐长度的整倍数。基准对齐长度从大成员的大小和系统对齐长度之间取较小的一个。32位系统中默认系统对齐长度是4字节。开发者可以使用#pragma pack()设置系统对齐长度。记忆口诀成员内部补齐每个成员起始地址必须是自身对齐数的整数倍不够就填空。结构体尾部补齐整体大小必须等于最大成员对齐数的整数倍。数组按数组元素类型算对齐char name[20]就当做 20 个 char。enum底层就是int占 4 字节。// 定义结构体 #include stdio.h struct S1 { int a; int b; int c; }; // 定义结构体 struct S2 { int a; // 4字节 double b; // 8字节 char c; // 1字节 }; // 定义结构体 struct S3 { int a; // 4 short b; // 2 double c; // 8 char d; // 1 }; // 定义结构体 struct S4 { int a; // 4 int b; // 4 long double c; // 16 char d; // 1 char e; // 1 char f; // 1 char g; // 1 }; // 修改系统对齐长度 #pragma pack(4) // 定义结构体 struct S5 { int a; // 4字节 double b; // 8字节 char c; // 1字节 }; #pragma pack(16) // 定义结构体 struct S6 { int a; // 4 int b[10]; // 40 要拆成10个4 char c; // 1 }; // 定义结构体 struct S7 { int a; struct { char b1; double b2; char b3; } b; int c; }; int main() { printf(S1: %zu \n, sizeof (struct S1)); // 12 printf(S2: %zu \n, sizeof (struct S2)); // 24 printf(S3: %zu \n, sizeof (struct S3)); // 24 printf(S4: %zu \n, sizeof (struct S4)); // 48 printf(S5: %zu \n, sizeof (struct S5)); // 16 printf(S6: %zu \n, sizeof (struct S6)); // 48 printf(S: %zu \n, sizeof (struct S7)); // 40 return 0; }结构体成员是数组数组的每个元素单独对齐不作为整体结构体成员还是结构体1. 计算基准对齐长度不把作为成员的结构体当做整体把内部成员取出来进行计算2. 计算总长度作为成员的结构体先整体对齐再与其他成员对齐