C语言 结构体

发布于:2025-08-31 ⋅ 阅读:(25) ⋅ 点赞:(0)

1. 什么是结构体?

结构体是一种用户自定义的数据类型,它允许你将多个不同类型的变量组合在一起,形成一个逻辑上的整体。这些变量称为结构体的成员(Members)


2. 如何定义结构体?

使用 struct 关键字来定义结构体。

语法:

struct 结构体标签 {
    数据类型 成员1;
    数据类型 成员2;
    // ... 更多成员
};

示例:定义一个表示学生的结构体

#include <stdio.h>
#include <string.h>

// 定义结构体类型 (这只是一份蓝图,尚未分配内存)
struct Student {
    int id;          // 学号
    char name[20];   // 姓名
    float score;     // 成绩
}; // 注意这里的分号不能丢

3. 如何声明和初始化结构体变量?

定义了结构体类型后,就可以像使用 intchar 一样来声明这种类型的变量。

方法一:先定义类型,再声明变量(推荐)

struct Student { // 定义类型
    int id;
    char name[20];
    float score;
};

int main() {
    struct Student stu1, stu2; // 声明两个结构体变量
    // ... 使用变量
    return 0;
}

方法二:定义类型的同时声明变量

struct Student {
    int id;
    char name[20];
    float score;
} stu1, stu2; // 同时声明了 stu1 和 stu2 两个变量

初始化结构体变量:
可以在声明时按顺序初始化所有成员,也可以指定成员初始化(C99标准支持)。

int main() {
    // 1. 按顺序初始化所有成员
    struct Student stu1 = {101, "Alice", 95.5f};

    // 2. 指定成员初始化(C99及以上),顺序可以打乱
    struct Student stu2 = { .name = "Bob", .score = 88.5f, .id = 102};

    // 3. 先声明,后逐个赋值
    struct Student stu3;
    stu3.id = 103;
    // stu3.name = "Charlie"; // 错误!数组不能直接赋值
    strcpy(stu3.name, "Charlie"); // 正确,使用strcpy函数拷贝字符串
    stu3.score = 91.0f;

    return 0;
}

4. 如何访问结构体成员?

使用成员访问运算符 . 来访问结构体变量的成员。

int main() {
    struct Student stu = {101, "Alice", 95.5f};

    // 访问成员并赋值
    printf("学号: %d\n", stu.id);
    printf("姓名: %s\n", stu.name);
    printf("成绩: %.1f\n", stu.score);

    // 修改成员的值
    stu.score = 98.0f;
    printf("修改后的成绩: %.1f\n", stu.score);

    return 0;
}

5. 结构体与指针

a) 指向结构体的指针

可以声明一个指针,让它指向一个结构体变量。

int main() {
    struct Student stu = {101, "Alice", 95.5f};
    struct Student *pStu; // 声明一个指向Student结构体的指针
    pStu = &stu;         // 让指针指向stu变量
b) 通过指针访问成员

通过指针访问结构体成员有两种方法:

  1. 使用 -> 运算符(箭头运算符):这是最常用、最清晰的方式。

  2. 使用 (*ptr).member:先解引用指针,再用 . 访问。

 // 方法1:使用 -> 运算符
    printf("学号 (通过指针): %d\n", pStu->id);
    printf("姓名 (通过指针): %s\n", pStu->name);
    pStu->score = 100.0f; // 通过指针修改成员

    // 方法2:使用 (*ptr).member
    printf("学号: %d\n", (*pStu).id); // *pStu 等价于 stu
    // 注意:(*pStu) 的括号是必须的,因为 . 的优先级比 * 高

-> 运算符是 (*ptr). 的语法糖,两者完全等价,但前者更简洁。


6. 结构体与函数

a) 结构体作为函数参数

结构体可以作为参数传递给函数。默认是值传递,即函数内部会得到一份原结构体的副本,修改副本不会影响原结构体。

// 值传递:修改不会影响原数据
void printStudent(struct Student s) {
    printf("ID: %d, Name: %s, Score: %.1f\n", s.id, s.name, s.score);
    s.score = 0; // 这只修改了函数内的副本,外面的原数据不变
}

int main() {
    struct Student stu = {101, "Alice", 95.5f};
    printStudent(stu);
    printf("原成绩未改变: %.1f\n", stu.score); // 输出 95.5
    return 0;
}
b) 结构体指针作为函数参数(按引用传递)

如果希望函数能修改原结构体的内容,或者结构体很大时为了避免拷贝整个结构体的开销,应该传递结构体指针

// 指针传递(引用传递):修改会影响原数据
void changeScore(struct Student *sPtr, float newScore) {
    sPtr->score = newScore; // 通过指针修改原结构体的成员
}

int main() {
    struct Student stu = {101, "Alice", 95.5f};
    changeScore(&stu, 88.0f); // 传递结构体的地址
    printf("成绩已被修改: %.1f\n", stu.score); // 输出 88.0
    return 0;
}

7. 结构体数组

可以创建元素为结构体的数组,用于管理多个相同类型的结构体数据。

int main() {
    // 声明并初始化一个结构体数组
    struct Student class[3] = {
        {101, "Alice", 95.5f},
        {102, "Bob", 88.0f},
        {103, "Charlie", 91.0f}
    };

    // 遍历结构体数组
    for (int i = 0; i < 3; i++) {
        printf("学生%d: %s, 分数: %.1f\n", class[i].id, class[i].name, class[i].score);
    }

    // 通过指针遍历
    struct Student *p;
    for (p = class; p < class + 3; p++) {
        printf("学生%d: %s, 分数: %.1f\n", p->id, p->name, p->score);
    }

    return 0;
}

8. typedef 关键字:为结构体创建别名

使用 typedef 可以为结构体类型定义一个更简短或更易读的别名,这样在声明变量时就不用每次都写 struct 关键字。

语法:

typedef struct 原结构体标签 {
    成员;
} 新类型名;

示例:

// 方法1:定义结构体同时用typedef
typedef struct {
    int id;
    char name[20];
    float score;
} Student; // Student 现在是一个类型别名,等价于 struct {...}

// 方法2:先定义结构体,再typedef
struct Person_ {
    int age;
    char name[20];
};
typedef struct Person_ Person; // 为 struct Person_ 起别名为 Person

int main() {
    // 现在声明变量可以省略 struct 关键字
    Student stu1 = {101, "Alice", 95.5f};
    Person p1 = {20, "David"};

    Student *pStu = &stu1;
    printf("%s\n", pStu->name);

    return 0;
}

总结

知识点 描述 关键语法
定义 创建一种新的复合数据类型 struct Tag { ... };
声明变量 创建该类型的实例 struct Tag var; 或使用 typedef 别名
初始化 给结构体变量赋初值 {val1, val2} 或 {.member=val}
访问成员 读写结构体中的数据 var.member
结构体指针 指向结构体的指针 struct Tag *ptr = &var;
指针访问成员 通过指针读写成员 ptr->member 或 (*ptr).member
函数参数 传递给函数 值传递:func(struct Tag var)
指针传递:func(struct Tag *ptr)
结构体数组 存储多个结构体 struct Tag arr[size];
typedef 为结构体类型创建别名 typedef struct { ... } NewName;

网站公告

今日签到

点亮在社区的每一天
去签到