9. 结构体嵌套声明

结构体嵌套声明是指结构体声明的内部可以再次声明结构体。其内部的结构体创建的变量可以作为外部结构体的成员变量。

下面我们声明一个结构体 struct scr 用来保存学生的语文成绩(chinese)、数学成绩(math)。

struct score 结构体声明如下:

struct scr {
    int chinese;
    int math;
};

下面我们有定义一个结构体 struct stu 用来保存学生的姓名(name)、年龄(age)和成绩(score)信息。

struct stu 结构体声明如下:

struct stu {
    char name[32];
    int age;
    struct scr score;
};

这样结构体 struct stu 就形成了一个内部嵌套结构体的结构体。我们把这种结构体的声明方式叫做结构体嵌套声明

上述结构体声明我们还可以将 struct scr 的声明放到 struct stu 的内部。如下所示:

struct stu {
    char name[32];
    int age;
    struct scr {
        int chinese;
        int math;
    } score;
};

这样我们就将两个结构体类型声明整理成了一个结构体类型声明。

那如何使用结构体 struct stu 来定义变量呢?

使用嵌套声明的结构体定义变量和初始化的语法和没有嵌套声明的结构体是一致的。

示例:

使用嵌套上述嵌套的结构体来创建变量并初始化。

// filename: struct_nesting_decl.c
#include <stdio.h>

struct stu {
    char name[32];
    int age;
    struct scr {
        int chinese;
        int math;
    } score;
};

int main(int argc, char * argv[]) {
    struct stu s1 = {"zhang san", 18, {100, 90}};
    struct stu s2 = {"li si", 16, {.math=30, .chinese=70}};

    // 李四重新考试取得了新的数学成绩为 60
    s2.score.math = 60;
    printf("%d 岁的 %s 语文成绩:%d, 数学成绩:%d\n",
        s1.age, s1.name, s1.score.chinese, s1.score.math);
    printf("%d 岁的 %s 语文成绩:%d, 数学成绩:%d\n",
        s2.age, s2.name, s2.score.chinese, s2.score.math);

    return 0;
}

编译和运行结果如下:

weimingze@mzstudio:~$ gcc -o struct_nesting_decl struct_nesting_decl.c
weimingze@mzstudio:~$ ./struct_nesting_decl
18 岁的 zhang san 语文成绩:100, 数学成绩:90
16 岁的 li si 语文成绩:70, 数学成绩:60

可见嵌套声明的结构体和普通结构体没有区别。只是有了包含关系。

实验:

将上述结构体嵌套定义的代码

struct stu {
    char name[32];
    int age;
    struct scr {
        int chinese;
        int math;
    } score;
};

改写成两个结构体分别声明,如下所示。

struct scr {
    int chinese;
    int math;
};

struct stu {
    char name[32];
    int age;
    struct scr  score;
};

然后使用上面的示例运行,看运行结果是否会有变化。

分析上述两种写法的区别是什么?