C 结构体

在 C 语言中,结构体(struct)是一种用户自定义的数据类型。它是一种复合类型,可以将不同数据类型的变量组合在一个名称下面,从而方便管理和使用。

C 结构体简介

在现实生活中,一个事物往往具有不同的属性,需要用不同的数据类型才能准确描述。比如一个学生的基本信息一般包括学号、姓名、性别、年龄等。其中学号一般是一个整型,姓名是一个字符数组,性别是一个字符型,年龄又是一个整型。

C 结构体

对于相同类型的多个数据,我们可以使用 “数组” 的方式来表示。但是对于不同类型的多个数据,此时又应该怎么表示呢?这个时候就需要借助结构体类型了。

在 C 语言中,我们可以使用结构体类型的方式来定义同一个事物的多种属性。虽然这些属性值的类型是不一样的,但是它们都是有着密切联系的,都用于描述同一个事物。

语法:

struct 类型名
{
    类型1  成员名1;
    类型2  成员名2;
    ……
    类型n  成员名3;
};

说明:

对于每一个成员来说,它的类型可以是基本类型(如整型、浮点型、字符型),也可以是数组,甚至还可以是另一个结构体类型。

需要特别注意,大括号后面的分号是不能省略的,如果省略就会报错。那么结构体类型是怎么使用的呢?我们来看一个简单例子就懂了。

示例 1:结构体的基本用法

#include <stdio.h>

// 定义一个结构体类型
struct Student
{
    int id;             // 学号
    char name[10];      // 姓名
    char gender;           // 性别,'m' 表示男,'f' 表示女
    int age;            // 年龄
};

int main(void)
{
    // 定义一个结构体变量
    struct Student stu = {1001, "Jack", 'm', 20};
    
    // 获取成员的值
    printf("学号:%d\n", stu.id);
    printf("姓名:%s", stu.name);
    return 0;
}

运行结果如下。

学号:1001
姓名:Jack

分析:

在这个例子中,我们使用 struct 关键字定义了一个名为 Student 的结构体类型。注意 Student 是一个类型名,并不是一个变量名。类型名和变量名怎么区分呢?比如 int a = 10;,int 就是一个类型名,而 a 就是一个变量名。

结构体类型和基本类型等不一样,int、float、char 等类型是 C 语言自带的,而结构体类型是需要手动自定义的。比如这里的 Student 类型就是我们自定义的一种结构体类型。结构体类型可以看出是一种 “组合型” 的类型,每一个成员都有属于自己的一种基本类型。不过要清楚一点,成员的类型可以相同,也可以不同,并不一定非要全部不同。

对于结构体的类型名,首字母一般大写。当然使用小写也是没关系的,只是不推荐这样做。因为首字母大写可以更加直观地看出来这是一个特殊的类型,以区分于其他数据类型。此外,结构体类型的定义一般放在 main() 函数 的外面,当然放在里面也是可以的。

定义好了一个类型之后,接下来就是使用这个类型来定义一个变量了。对于基本类型来说,我们都是使用 “类型 变量名=值;” 这样的方式来定义一个变量,比如 int a = 10;。对于结构体类型来说,我们同样是使用这种方式来定义一个结构体变量。需要注意的是,结构体变量在声明时需要同时赋值初始化(即赋值),而不能分开来写。

// 正确
struct Student stu = {1001, "Jack", 'm', 20};

// 错误
struct Student stu;
stu = {1001, "Jack", 'm', 20};

结构体类型和结构体变量,这两个是不一样的东西,小伙伴们不要搞混了。结构体类型是一种 “类型”,而结构体变量是一个 “变量”。

最后,如果想要获取结构体变量中某一个成员的值,我们可以使用点运算符(.) 来实现,也就是 “变量名.成员名”。比如上面是 stu.id 就是获取 id 成员的值,而 stu.name 就是获取 name 成员的值。

通过上面这个例子,小伙伴们对结构体类型也有一定的了解了。接下来我们再来深入了解一下各个语法细节。

提示: C 语言中的 “结构体(struct)” 与其他语言(如 Python、Java 等)中的 “类(class)” 相似,小伙伴们可以对比理解一下。

C 定义结构体变量

对于结构体类型来说,如果想要定义一个结构体类型的变量,我们主要有以下 3 种方式。

1. 先定义类型,后定义变量

struct Student
{
    int id;             // 学号
    char name[10];      // 姓名
    char gender;           // 性别,'m' 表示男,'f' 表示女
    int age;            // 年龄
};
struct Student stu = {1001, "Jack", 'm', 20};

2. 定义类型的同时定义变量(带类型名)

struct Student
{
    int id;             // 学号
    char name[10];      // 姓名
    char gender;           // 性别,'m' 表示男,'f' 表示女
    int age;            // 年龄
} stu = {1001, "Jack", 'm', 20};

3. 定义类型的同时定义变量(不带类型名)

struct
{
    int id;             // 学号
    char name[10];      // 姓名
    char gender;           // 性别,'m' 表示男,'f' 表示女
    int age;            // 年龄
} stu = {1001, "Jack", 'm', 20};

对于第 2 种方式,我们在定义类型的同时,可以定义多个变量,而不仅仅是一个变量。

对于第 3 种方式,这种方式是不带一个类型名的,但需要在后面紧接着去定义一个结构体变量。这种方式在实际开发中用得比较少,简单了解一下即可。

示例 2:定义多个结构体变量

#include <stdio.h>

// 定义结构体类型
struct Student
{
    int id;             // 学号
    char name[10];      // 姓名
    char gender;           // 性别,'m' 表示男,'f' 表示女
    int age;            // 年龄
};

int main(void)
{
    // 定义多个结构体变量
    struct Student stu1 = {1001, "Jack", 'm', 20};
    struct Student stu2 = {1002, "Lucy", 'f', 21};
    struct Student stu3 = {1003, "Tony", 'm', 19};

    // 获取成员的值
    printf("Jack 的学号:%d\n", stu1.id);
    printf("Lucy 的学号:%d\n", stu2.id);
    printf("Tony 的学号:%d", stu3.id);

    return 0;
}

运行结果如下。

Jack 的学号:1001
Lucy 的学号:1002
Tony 的学号:1003

分析:

在这个例子中,我们定义了 3 个结构体变量:stu1、stu2、stu3,它们都属于 Student 类型,因此都拥有相同的成员(属性):id、name、gender、age。虽然拥有相同的成员,但是成员的值并不一定就是相同的。

C 修改结构体成员的值

对于结构体变量来说,我们可以使用点运算符(.)来获取一个成员的值。如果想要修改一个成员的值,我们同样也是通过点运算符(.)来实现。

语法:

变量名.成员名 = 新值;

示例 3:修改成员的值

#include <stdio.h>

struct Student
{
    int id;             // 学号
    char name[10];      // 姓名
    char gender;           // 性别,'m' 表示男,'f' 表示女
    int age;            // 年龄
};

int main(void)
{
    struct Student stu = {1001, "Jack", 'm', 20};
    
    // 修改成员的值
    stu.id = 1002;

    // 获取成员的值
    printf("学号:%d", stu.id);
    return 0;
}

运行结果如下。

学号:1002

分析:

结构体变量 stu 的 id 成员初始值为 1001,stu.id = 1002; 表示将 id 成员的值修改为 1002。当然了,小伙伴们可以尝试修改一下其他成员的值。

结构体类型其实非常简单,它其实就是将多种数据类型组合成一个混合型的类型,这样我们就可以用它来表示某一个事物的多个属性。其中结构体成员的类型可以相同,也可以不同。成员的类型除了可以是基本类型(如 int、float、char),还可以是数组指针等。

如果小伙伴们有接触过 Python、Java 等编程语言,会发现结构体类型和面向对象中 “类的定义” 很相似。但是结构体类型和面向对象还是有着本质上的区别的,比如面向对象中一个类除了有属性之外还有方法,而结构体类型是没有方法这种东西的。对于具体某一个功能,我们依旧是使用面向过程的方式来实现。

注意: 对于 int、char 等基本类型的成员,我们可以直接用 “=” 赋值修改。但对于 char 数组类型的成员(如 name),是不能直接用 “=” 赋值的,而必须使用 strcpy() 函数,例如 strcpy(stu.name, "Rose");。

最后,对于结构体类型,我们可以总结出以下非常重要的 4 点。

  • 结构体类型是一种 “类型”,结构体变量是一个 “变量”。结构体变量是使用结构体类型来定义的。
  • 结构体类型是一种 “组合” 类型,它由多个其他类型的成员组合而成。
  • 结构体所有成员的类型可以是相同的,也可以是不同的。
  • 通过点运算符来获取或修改一个结构体成员的值,比如 stu.name。

上一篇: C 回调函数

下一篇: C 结构体数组

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号