C语言(结构体)

[1. 基础概念](#1. 基础概念)

[1.1 什么是结构体](#1.1 什么是结构体)

[1.2 结构体的组成](#1.2 结构体的组成)

[1.3 为什么要用结构体](#1.3 为什么要用结构体)

[2. 基本用法](#2. 基本用法)

[2.1 定义结构体类型](#2.1 定义结构体类型)

[2.2 声明结构体变量](#2.2 声明结构体变量)

[2.3 结构体初始化](#2.3 结构体初始化)

[2.4 访问结构体成员](#2.4 访问结构体成员)

[3. 结构体数组](#3. 结构体数组)

[3.1 定义和使用](#3.1 定义和使用)

[4. 结构体指针](#4. 结构体指针)

[4.1 基本使用](#4.1 基本使用)

[4.2 动态内存分配](#4.2 动态内存分配)

[5. 结构体与函数](#5. 结构体与函数)

[5.1 结构体作为函数参数](#5.1 结构体作为函数参数)

[6. typedef简化](#6. typedef简化)

[6.1 使用typedef](#6.1 使用typedef)

[7. 嵌套结构体](#7. 嵌套结构体)

[7.1 结构体嵌套](#7.1 结构体嵌套)

[8. 综合示例](#8. 综合示例)

[8.1 学生管理系统](#8.1 学生管理系统)

[9. 重要知识点总结](#9. 重要知识点总结)

[9.1 核心要点](#9.1 核心要点)

[9.2 常见错误](#9.2 常见错误)

[9.3 最佳实践](#9.3 最佳实践)


1. 基础概念

1.1 什么是结构体

  • 结构体(struct):用户自定义的复合数据类型

  • 作用:将多个不同类型的变量组合成一个整体

  • 类比:就像Excel中的一行数据,包含姓名、年龄、成绩等不同列

1.2 结构体的组成

复制代码
 struct 结构体名 {
     数据类型 成员1;
     数据类型 成员2;
     // ...
 };

1.3 为什么要用结构体

  1. 组织相关数据:把逻辑相关的数据放一起

  2. 代码更清晰:提高可读性和可维护性

  3. 函数参数简化:一次传递多个相关数据

  4. 模拟现实对象:如学生、员工、商品等


2. 基本用法

2.1 定义结构体类型

cpp 复制代码
// 定义学生结构体类型
 struct Student {
     char name[20];  // 姓名
     int age;        // 年龄
     float score;    // 成绩
 };

2.2 声明结构体变量

cpp 复制代码
 #include <stdio.h>
 ​
 int main() {
     // 方法1:先定义类型,再声明变量
     struct Student stu1;
     
     // 方法2:定义时直接声明变量
     struct Student2 {
         char name[20];
         int age;
     } stu2, stu3;  // 同时声明两个变量
     
     // 方法3:匿名结构体(不推荐)
     struct {
         char name[20];
         int age;
     } stu4;
     
     return 0;
 }

2.3 结构体初始化

cpp 复制代码
#include <stdio.h>
 #include <string.h>
 ​
 struct Student {
     char name[20];
     int age;
     float score;
 };
 ​
 int main() {
     // 方法1:按顺序初始化
     struct Student stu1 = {"张三", 18, 90.5};
     
     // 方法2:指定成员初始化(C99)
     struct Student stu2 = {
         .name = "李四",
         .score = 85.5,
         .age = 20  // 顺序可以打乱
     };
     
     // 方法3:先声明后赋值
     struct Student stu3;
     strcpy(stu3.name, "王五");  // 字符串需要strcpy
     stu3.age = 19;
     stu3.score = 88.0;
     
     // 方法4:全部初始化为0
     struct Student stu4 = {0};
     
     return 0;
 }

2.4 访问结构体成员

cpp 复制代码
#include <stdio.h>
 ​
 struct Point {
     int x;
     int y;
 };
 ​
 int main() {
     struct Point p1 = {10, 20};
     
     // 使用点运算符(.)访问成员
     printf("x坐标: %d\n", p1.x);
     printf("y坐标: %d\n", p1.y);
     
     // 修改成员值
     p1.x = 30;
     p1.y = 40;
     
     printf("修改后坐标: (%d, %d)\n", p1.x, p1.y);
     
     return 0;
 }

3. 结构体数组

3.1 定义和使用

cpp 复制代码
#include <stdio.h>
 ​
 struct Student {
     char name[20];
     int score;
 };
 ​
 int main() {
     // 定义结构体数组
     struct Student class[3] = {
         {"张三", 85},
         {"李四", 92},
         {"王五", 78}
     };
     
     // 访问数组元素
     printf("学生信息:\n");
     for(int i = 0; i < 3; i++) {
         printf("%s的成绩是: %d\n", class[i].name, class[i].score);
     }
     
     // 修改数组元素
     class[0].score = 90;
     printf("\n修改后: %s的成绩是: %d\n", class[0].name, class[0].score);
     
     return 0;
 }

4. 结构体指针

4.1 基本使用

cpp 复制代码
 #include <stdio.h>
 ​
 struct Student {
     char name[20];
     int age;
 };
 ​
 int main() {
     struct Student stu = {"小明", 18};
     struct Student *p = &stu;  // 指向结构体的指针
     
     // 通过指针访问成员:使用箭头运算符(->)
     printf("姓名: %s\n", p->name);
     printf("年龄: %d\n", p->age);
     
     // 通过指针修改成员
     p->age = 20;
     printf("修改后年龄: %d\n", stu.age);  // stu.age也变为20
     
     return 0;
 }

4.2 动态内存分配

cpp 复制代码
#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 ​
 struct Book {
     char title[50];
     float price;
 };
 ​
 int main() {
     // 动态分配一个结构体
     struct Book *book = (struct Book*)malloc(sizeof(struct Book));
     
     if(book == NULL) {
         printf("内存分配失败\n");
         return 1;
     }
     
     // 使用指针访问
     strcpy(book->title, "C语言程序设计");
     book->price = 45.5;
     
     printf("书名: %s\n", book->title);
     printf("价格: %.2f\n", book->price);
     
     // 释放内存
     free(book);
     
     return 0;
 }

5. 结构体与函数

5.1 结构体作为函数参数

cpp 复制代码
#include <stdio.h>
 ​
 struct Point {
     int x;
     int y;
 };
 ​
 // 值传递:传递整个结构体的副本
 void printPoint(struct Point p) {
     printf("坐标: (%d, %d)\n", p.x, p.y);
 }
 ​
 // 指针传递:只传递地址,效率更高
 void movePoint(struct Point *p, int dx, int dy) {
     p->x += dx;
     p->y += dy;
 }
 ​
 // 返回结构体
 struct Point createPoint(int x, int y) {
     struct Point p;
     p.x = x;
     p.y = y;
     return p;
 }
 ​
 int main() {
     struct Point p1 = {10, 20};
     
     printPoint(p1);  // 值传递
     
     movePoint(&p1, 5, 5);  // 指针传递
     printf("移动后: ");
     printPoint(p1);
     
     struct Point p2 = createPoint(30, 40);
    printPoint(p2);
     
     return 0;
 }

6. typedef简化

6.1 使用typedef

cpp 复制代码
 #include <stdio.h>
 ​
 // 用typedef创建别名
 typedef struct {
     char name[20];
     int age;
 } Person;  // Person就是类型名,不需要写struct Person
 ​
 typedef struct Node {
     int data;
     struct Node* next;  // 这里还需要struct
 } Node;
 ​
 int main() {
     // 使用typedef后的简洁声明
     Person p1 = {"张三", 25};
     Person p2;
     
     printf("姓名: %s, 年龄: %d\n", p1.name, p1.age);
     
     return 0;
 }

7. 嵌套结构体

7.1 结构体嵌套

cpp 复制代码
 #include <stdio.h>
 ​
 // 定义日期结构体
 struct Date {
     int year;
     int month;
     int day;
 };
 ​
 // 学生结构体嵌套日期结构体
 struct Student {
     char name[20];
     struct Date birthday;  // 嵌套结构体
     float score;
 };
 ​
 int main() {
     // 初始化嵌套结构体
     struct Student stu = {
         "李华",
         {2000, 5, 15},  // 初始化birthday
         90.5
     };
     
     // 访问嵌套成员
     printf("姓名: %s\n", stu.name);
     printf("生日: %d年%d月%d日\n", 
            stu.birthday.year, 
            stu.birthday.month, 
            stu.birthday.day);
     printf("成绩: %.1f\n", stu.score);
     
     return 0;
 }

8. 综合示例

8.1 学生管理系统

cpp 复制代码
#include <stdio.h>
 #include <string.h>
 ​
 #define MAX_STUDENTS 10
 ​
 // 学生结构体
 typedef struct {
     int id;
     char name[20];
     float score;
 } Student;
 ​
 // 全局学生数组
 Student students[MAX_STUDENTS];
 int student_count = 0;
 ​
 // 添加学生
 void add_student() {
     if(student_count >= MAX_STUDENTS) {
         printf("学生人数已满!\n");
         return;
     }
     
     Student s;
     printf("请输入学号: ");
     scanf("%d", &s.id);
     printf("请输入姓名: ");
     scanf("%s", s.name);
     printf("请输入成绩: ");
     scanf("%f", &s.score);
     
     students[student_count] = s;
     student_count++;
     printf("添加成功!\n");
 }
 ​
 // 显示所有学生
 void show_students() {
     if(student_count == 0) {
         printf("没有学生信息!\n");
         return;
     }
     
     printf("\n学号\t姓名\t成绩\n");
     printf("-------------------\n");
     for(int i = 0; i < student_count; i++) {
         printf("%d\t%s\t%.1f\n", 
                students[i].id, 
                students[i].name, 
                students[i].score);
     }
 }
 ​
 // 查找学生
 void find_student() {
     int id;
     printf("请输入要查找的学号: ");
     scanf("%d", &id);
     
     for(int i = 0; i < student_count; i++) {
         if(students[i].id == id) {
             printf("找到学生: %s, 成绩: %.1f\n", 
                    students[i].name, students[i].score);
             return;
         }
     }
     printf("未找到学号为 %d 的学生\n", id);
 }
 ​
 // 计算平均分
 void average_score() {
     if(student_count == 0) {
         printf("没有学生信息!\n");
         return;
     }
     
     float sum = 0;
     for(int i = 0; i < student_count; i++) {
         sum += students[i].score;
     }
     
     printf("平均成绩: %.2f\n", sum / student_count);
 }
 ​
 int main() {
     int choice;
     
     do {
         printf("\n=== 学生管理系统 ===\n");
         printf("1. 添加学生\n");
         printf("2. 显示所有学生\n");
         printf("3. 查找学生\n");
         printf("4. 计算平均分\n");
         printf("0. 退出\n");
         printf("请选择: ");
         scanf("%d", &choice);
         
         switch(choice) {
             case 1: add_student(); break;
             case 2: show_students(); break;
             case 3: find_student(); break;
             case 4: average_score(); break;
             case 0: printf("谢谢使用!\n"); break;
             default: printf("无效选择!\n");
         }
     } while(choice != 0);
     
     return 0;
 }

9. 重要知识点总结

9.1 核心要点

  1. 内存对齐:结构体大小可能大于成员大小之和

  2. . 和 -> 的区别.用于结构体变量,->用于结构体指针

  3. 结构体比较 :不能直接用==比较,需要逐个比较成员

  4. 结构体赋值 :可以直接用=赋值(浅拷贝)

9.2 常见错误

cpp 复制代码
 // 错误1:结构体比较
 struct Point {int x; int y;} p1 = {1,2}, p2 = {1,2};
 // if(p1 == p2) { ... }  // 错误!不能直接比较
 ​
 // 错误2:结构体包含指针时的赋值问题
 struct Student {
     char *name;  // 指针成员
     int age;
 };
 ​
 struct Student s1, s2;
 s1.name = "Tom";  // s1.name指向常量区
 s2 = s1;          // 浅拷贝,s2.name也指向同一地址

9.3 最佳实践

  1. 尽量使用typedef简化类型名

  2. 结构体作为函数参数时,使用指针提高效率

  3. 动态分配的结构体要记得释放内存

  4. 考虑结构体的内存对齐,合理安排成员顺序

相关推荐
Prince-Peng9 小时前
技术架构系列 - 详解Redis
数据结构·数据库·redis·分布式·缓存·中间件·架构
只是懒得想了10 小时前
C++实现密码破解工具:从MD5暴力破解到现代哈希安全实践
c++·算法·安全·哈希算法
码农水水10 小时前
得物Java面试被问:消息队列的死信队列和重试机制
java·开发语言·jvm·数据结构·机器学习·面试·职场和发展
m0_7369191010 小时前
模板编译期图算法
开发语言·c++·算法
dyyx11110 小时前
基于C++的操作系统开发
开发语言·c++·算法
m0_7369191010 小时前
C++安全编程指南
开发语言·c++·算法
蜡笔小马10 小时前
11.空间索引的艺术:Boost.Geometry R树实战解析
算法·r-tree
-Try hard-10 小时前
数据结构:链表常见的操作方法!!
数据结构·算法·链表·vim
2301_7903009610 小时前
C++符号混淆技术
开发语言·c++·算法
我是咸鱼不闲呀11 小时前
力扣Hot100系列16(Java)——[堆]总结()
java·算法·leetcode