[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 为什么要用结构体
-
组织相关数据:把逻辑相关的数据放一起
-
代码更清晰:提高可读性和可维护性
-
函数参数简化:一次传递多个相关数据
-
模拟现实对象:如学生、员工、商品等
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 核心要点
-
内存对齐:结构体大小可能大于成员大小之和
-
. 和 -> 的区别 :
.用于结构体变量,->用于结构体指针 -
结构体比较 :不能直接用
==比较,需要逐个比较成员 -
结构体赋值 :可以直接用
=赋值(浅拷贝)
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 最佳实践
-
尽量使用
typedef简化类型名 -
结构体作为函数参数时,使用指针提高效率
-
动态分配的结构体要记得释放内存
-
考虑结构体的内存对齐,合理安排成员顺序