结构体
strusct结构体定义通常放在全局作用域(即函数之外)或局部作用域(函数内部)中。当我们在全局作用域中定义结构体时,这个结构体类型可以在定义之后的任何地方使用,包括各个函数内部。但是,结构体定义并不分配内存,它只是定义了一种数据类型。
// 基本结构体定义
struct Student {
char name[20];
int age;
float score;
};
// 定义同时声明变量
struct Point {
int x;
int y;
} p1, p2;
// 使用typedef简化
typedef struct {
char title[50];
char author[30];
float price;
} Book;
typedef
**typedef**是C语言中的一个关键字,用于为已有的数据类型创建新的类型别名。
typedef struct {
int id;
int age;
char *name;
float score;
} Student1;
typedef struct Student1 Student;//为 struct Student1 结构体类型创建一个新的别名 Student。
int main() {
Student stu1;
return 0;
}
结构体嵌套
typedef struct {
int year;//年
int month;//月
int day;//日
}Birthday;
typedef struct {
int id;//学号
int age;//年龄
char *name;//姓名
float score;//成绩
Birthday birthday;
}Student1;
int main() {
Student1 stu1,stu2,stu3;//可以定义多个变量名
stu1.birthday.day = 1;//使用点进行多层访问
return 0;
}
结构体赋值及打印
结构体指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int id;
char name[20];
int age;
float score;
} Student;
int main() {
// 1. 声明结构体变量和指针
Student stu1 = {1, "张三", 20, 85.5};
Student *pStu; // 声明结构体指针
// 2. 让指针指向结构体变量
pStu = &stu1;
// 3. 通过指针访问结构体成员(使用箭头运算符 ->)
printf("通过指针访问:\n");
printf("学号: %d\n", pStu->id);
printf("姓名: %s\n", pStu->name);
printf("年龄: %d\n", pStu->age);
printf("成绩: %.1f\n", pStu->score);
// 4. 通过指针修改结构体成员
pStu->age = 21;
pStu->score = 90.0;
strcpy(pStu->name, "张三丰");
printf("\n修改后:\n");
printf("学号: %d\n", pStu->id);
printf("姓名: %s\n", pStu->name);
printf("年龄: %d\n", pStu->age);
printf("成绩: %.1f\n", pStu->score);
return 0;
}
嵌套结构体指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int year;
int month;
int day;
} Birthday;
typedef struct {
int id;
char name[20];
Birthday birthday; // 嵌套结构体
float score;
} Student;
// 创建学生
Student* createStudent(int id, const char *name, int year, int month, int day, float score) {
Student *pStu = (Student*)malloc(sizeof(Student));
if (pStu != NULL) {
pStu->id = id;
strcpy(pStu->name, name);
pStu->birthday.year = year;
pStu->birthday.month = month;
pStu->birthday.day = day;
pStu->score = score;
}
return pStu;
}
// 打印学生信息
void printStudent(const Student *pStu) {
if (pStu == NULL) return;
printf("学生信息:\n");
printf(" 学号: %d\n", pStu->id);
printf(" 姓名: %s\n", pStu->name);
printf(" 生日: %d年%d月%d日\n",
pStu->birthday.year,
pStu->birthday.month,
pStu->birthday.day);
printf(" 成绩: %.1f\n", pStu->score);
}
// 通过指针修改生日
void updateBirthday(Student *pStu, int year, int month, int day) {
if (pStu != NULL) {
pStu->birthday.year = year;
pStu->birthday.month = month;
pStu->birthday.day = day;
}
}
int main() {
// 创建学生指针
Student *pStu = createStudent(1, "小明", 2000, 5, 15, 85.5);
if (pStu != NULL) {
printStudent(pStu);
// 修改生日
updateBirthday(pStu, 2001, 6, 20);
printf("\n修改生日后:\n");
printStudent(pStu);
// 直接通过指针访问嵌套结构体
printf("\n直接访问嵌套结构体:\n");
printf("年份: %d\n", pStu->birthday.year);
printf("月份: %d\n", pStu->birthday.month);
printf("日期: %d\n", pStu->birthday.day);
free(pStu);
}
return 0;
}
结构体指针的重要知识点
- 箭头运算符:
p->member等价于(*p).member - 内存管理:动态分配的结构体指针必须手动释放
- 函数参数:传递指针比传递整个结构体更高效
- 深拷贝与浅拷贝:包含指针的结构体需要深拷贝
- const保护:使用
const Student *p防止意外修改