C: 结构体

结构体就像一张定制表格:把不同类型的信息(姓名、年龄、成绩)打包在一起,变成一个整体来管理。

1. struct 定义与声明

(1) 定义结构体类型

C
struct Student {
    char name[20];
    int age;
    float score;
};

这定义了一个类型 struct Student,注意末尾的分号不能省。

(2) 声明结构体变量

C
struct Student s1;
struct Student s2, s3;

也可以在定义类型的同时声明变量:

C
struct Point {
    int x;
    int y;
} p1, p2;

(3) 匿名结构体

如果只用一次,可以不写类型名:

C
struct {
    int width;
    int height;
} box;
⚠️ 匿名结构体无法再声明新变量,通常只用于一次性场景。


2. 结构体变量初始化

(1) 顺序初始化

C
struct Student s1 = {"张三", 20, 89.5};

(2) 指定成员初始化(C99)

C
struct Student s2 = {.name = "李四", .score = 92.0, .age = 21};
💡 指定成员初始化可以不按顺序,未指定的成员自动清零。

(3) 部分初始化

C
struct Student s3 = {"王五"};

name 被初始化,其余成员自动为 0。


3. 成员访问

(1) 点运算符 .

通过结构体变量访问成员:

C
struct Student s = {"赵六", 19, 78.5};
printf("姓名: %s\n", s.name);
printf("年龄: %d\n", s.age);
s.score = 85.0;

(2) 箭头运算符 ->

通过结构体指针访问成员:

C
struct Student s = {"赵六", 19, 78.5};
struct Student *ps = &s;
printf("姓名: %s\n", ps->name);
ps->age = 20;

ps->name 等价于 (*ps).name-> 是语法糖,用指针时更简洁。

💡 口诀:变量用点,指针用箭头。

▶ 示例

C
#include <stdio.h>

struct Book {
    char title[50];
    char author[30];
    float price;
};

int main(void) {
    struct Book b1 = {.title = "C程序设计语言", .author = "K&R", .price = 45.0};
    struct Book *pb = &b1;

    printf("书名: %s\n", pb->title);
    printf("作者: %s\n", pb->author);
    printf("价格: %.1f\n", pb->price);

    pb->price = 55.0;
    printf("折扣后: %.1f\n", b1.price);
    return 0;
}
▶ 试一试
TEXT 📖 仅展示
书名: C程序设计语言
作者: K&R
价格: 45.0
折扣后: 55.0

4. 结构体数组

把多个结构体放在数组里统一管理。

C
struct Student class[3] = {
    {"张三", 20, 89.5},
    {"李四", 21, 92.0},
    {"王五", 19, 78.0}
};

for (int i = 0; i < 3; i++) {
    printf("%s %d %.1f\n", class[i].name, class[i].age, class[i].score);
}
TEXT 📖 仅展示
张三 20 89.5
李四 21 92.0
王五 19 78.0

用指针遍历结构体数组:

C
struct Student *p = class;
for (int i = 0; i < 3; i++, p++) {
    printf("%s %.1f\n", p->name, p->score);
}

5. 结构体指针

结构体指针最常见的用法:在函数间传递结构体时避免拷贝整块数据。

C
void print_student(struct Student *ps) {
    printf("%s, %d岁, %.1f分\n", ps->name, ps->age, ps->score);
}

int main(void) {
    struct Student s = {"张三", 20, 89.5};
    print_student(&s);
    return 0;
}
TEXT 📖 仅展示
张三, 20岁, 89.5分
⚠️ 传值会拷贝整个结构体,如果成员多、含大数组,开销很大。传指针只拷贝一个地址。


6. 结构体作为函数参数

(1) 传值

C
void add_score(struct Student s, float bonus) {
    s.score += bonus;
}
⚠️ 传值时函数内修改的是副本,不会影响原变量。

(2) 传指针

C
void add_score(struct Student *s, float bonus) {
    s->score += bonus;
}

函数内通过指针修改,直接影响原变量。

▶ 示例

C
#include <stdio.h>

struct Score {
    char name[20];
    int chinese;
    int math;
    int english;
};

int total(struct Score *s) {
    return s->chinese + s->math + s->english;
}

void boost(struct Score *s, int bonus) {
    s->chinese += bonus;
    s->math += bonus;
    s->english += bonus;
}

int main(void) {
    struct Score stu = {.name = "周七", .chinese = 80, .math = 75, .english = 88};
    printf("原始总分: %d\n", total(&stu));
    boost(&stu, 5);
    printf("加分后总分: %d\n", total(&stu));
    return 0;
}
▶ 试一试
TEXT 📖 仅展示
原始总分: 243
加分后总分: 258

7. 结构体赋值与比较

(1) 赋值

同类型结构体可以直接赋值,成员逐个拷贝:

C
struct Student s1 = {"张三", 20, 89.5};
struct Student s2;
s2 = s1;

(2) 比较

⚠️ 结构体不能用 ==!= 比较,必须逐个成员比较:

C
int equal(struct Student *a, struct Student *b) {
    return a->age == b->age && a->score == b->score;
}

8. 结构体嵌套

结构体的成员可以是另一个结构体:

C
struct Date {
    int year;
    int month;
    int day;
};

struct Employee {
    char name[20];
    struct Date birthday;
    float salary;
};

struct Employee e = {"陈八", {1995, 6, 15}, 8000.0};
printf("生日: %d-%02d-%02d\n", e.birthday.year, e.birthday.month, e.birthday.day);
TEXT 📖 仅展示
生日: 1995-06-15

❓ 常见问题

Q .-> 有什么区别?
A . 用于结构体变量访问成员,-> 用于结构体指针访问成员。p->name 等价于 (*p).name
Q 结构体可以用 == 比较吗?
A 不能。C 语言不支持结构体的 == 比较,需要逐成员比较或用 memcmp(注意填充字节问题)。
Q 结构体传值和传指针怎么选?
A 一般传指针——效率高、可修改原数据。只读场景加 const 保护:const struct Student *s
Q 结构体定义后面为什么必须加分号?
A 因为定义末尾可以紧跟变量声明列表,分号告诉编译器列表结束,不加会报语法错误。

📖 小节

📝 作业

  1. 定义 struct Rectangle 含 width 和 height,编写函数 float area(struct Rectangle *r)float perimeter(struct Rectangle *r),在 main 中计算输出
  2. 定义 struct Date,编写函数 int date_compare(struct Date *a, struct Date *b),返回 -1/0/1 表示 a 早于/等于/晚于 b
  3. 定义学生结构体数组(5人),按成绩从高到低排序并输出
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏