首页 > 编程笔记 > C语言笔记 阅读:12

C语言结构体定义和使用(非常详细)

读者已经学习过 C 语言的许多基本数据类型,如整型 int、字符型 char 等,还学习了数组这种构造类型。数组中,所有的数据都是同一类型,调用起来非常方便。

除此以外,有时我们需要定义一些复杂的数据类型,它可能包括多个不同属性,每个属性需要用不同的类型来表示。该怎么实现呢?

C语言中,可以把一些有内在联系的不同变量组织起来,封装成一个整体,即定义成一个结构体(structure),以此来表示一种新的数据类型。之后,就可以像处理基本数据类型那样,对结构体类型进行各种操作。

C语言结构体的声明

结构体是一种构造类型,它由若干成员组成。其成员可以是一个基本数据类型,也可以是另一个构造类型。声明一个结构体的过程,就是创建一种新的类型名的过程。

声明结构体时使用的关键字是 struct,其一般形式如下:
struct 结构体名
{
    成员列表
};
关键字 struct 表示声明的是一个结构体,“结构体名”表示要创建的新类型名,大括号中的“成员列表”包括构成该结构体的所有成员。注意,声明结构体时大括号后的分号“;”不能遗漏。

例如,商品一般包括产品名称、形状、颜色、功能、价格和产地等属性,如下图所示:


图 1 “商品”类型

很显然,“商品”这种类型并不能使用任何一种基本类型来表示,而需要为其构造一个结构体。

下面来创建“商品(Product)”这种类型,声明代码如下:
struct Product
{ /*声明结构体*/
    char cName[10];    /*产品名称*/
    char cShape[20];   /*形状*/
    char cColor[10];   /*颜色*/
    char cFunc[20];    /*功能*/
    int iPrice;        /*价格*/
    char cArea[20];    /*产地*/
};

struct Product product1; /*定义结构体类型变量*/
struct Product product2;
上述代码使用关键字 struct 声明了一个名为 Product 的结构体类型,在结构体中定义了 6 个变量,分别表示产品名称、形状、颜色、功能、价格和产地,并为其设置了相对应的类型。

C语言结构体变量的定义

声明完结构体后,就创建了一种新的类型名,后续就可以使用这种新的类型名定义变量。

定义结构体变量的方式有如下 3 种。

1) 先声明结构体类型,再定义变量。例如,使用前面声明的 Product 结构体类型定义两个结构体变量 product1 和 product2,代码如下:
struct Product  /* 声明结构体 */
{
    char cName[10];    /* 产品名称 */
    char cShape[20];   /* 形状 */
    char cColor[10];   /* 颜色 */
    char cFunc[20];    /* 功能 */
    int iPrice;        /* 价格 */
    char cArea[20];    /* 产地 */
};

struct Product product1;  /* 定义结构体类型变量 */
struct Product product2;
struct Product 是结构体类型名,而 product1 和 product2 是结构体变量名。既然都是使用 Product 类型定义的变量,那么这两个变量就具有相同的结构。

在一些大型开发中,为了便于修改和使用,常常将结构体类型的声明放在一个头文件中,这样在其他源文件中如果需要使用该结构体类型,则可以用 #include 命令将该头文件包含到源文件中。

定义一个基本类型的变量与定义一个结构体类型变量的不同之处在于:定义结构体变量不仅要求指定变量为结构体类型,而且要求指定为某一特定的结构体类型,如 struct Product;而定义基本类型的变量时(如整型变量),只需要指定 int 型即可。

定义结构体变量后,系统就会为其分配内存单元。例如,product1 和 product2 在内存中各占 84 字节(10+20+10+20+4+20)。

2) 声明结构类型的同时定义结构体变量。例如:
struct Product
{
    char cName[10];    /* 产品名称 */
    char cShape[20];   /* 形状 */
    char cColor[10];   /* 颜色 */
    char cFunc[20];    /* 功能 */
    int iPrice;        /* 价格 */
    char cArea[20];    /* 产地 */
}product1,product2; /* 定义结构体变量 */

3) 直接定义结构体类型变量(此时不需要给出结构体名称)。例如:
struct
{
    char cName[10];    /* 产品名称 */
    char cShape[20];   /* 形状 */
    char cColor[10];   /* 颜色 */
    int iPrice;        /* 价格 */
    char cArea[20];    /* 产地 */
}product1,product2; /* 定义结构体变量 */
需要注意的是,类型与变量是不同的。例如,只能对变量进行赋值操作,不能对类型进行操作。这就像使用 int 型定义变量 int,可以为 int 赋值,但不能为 int 赋值。编译时,不对类型分配空间,只对变量分配空间。

结构体的成员仍然可以是结构体类型的变量。例如:
struct date
{
    int year;         /* 年 */
    int month;        /* 月 */
    int day;          /* 日 */
};
struct student
{
    int num;
    char name[30];    /* 学号 */
    char sex;         /* 姓名 */
    int age;          /* 性别 */
    struct date birthday; /* 年龄 */
}student1,student2; /* 出生日期 */
以上代码声明了一个 date 结构体类型,成员包括年、月、日;还声明了一个 student 结构类型,并且定义了两个结构体变量 student1 和 student2。在 struct student 结构体类型中,可以看到有一个成员是表示学生的出生日期,使用的是 struct date 结构体类型。

C语言结构体变量的使用

定义了结构体类型变量以后,就可以使用该变量,使用形式为:

结构变量名.成员名

例如:
product1.cName="Icebox";
product1.iPrice=2000;
对结构体变量进行赋值、存取或运算,实质上就是对结构体成员进行操作。上面的赋值语句就是对 product1 结构体变量中的成员 cName 和 iPrice 两个变量进行赋值。

需要注意的是,不能直接将结构体变量作为一个整体进行输入和输出。例如,不能将 product1 和 product2 采用如下方式输出:
printf("%s%s%s%d%s",product1);
printf("%s%s%s%d%s",product2);
如果成员本身又属于一个结构体类型,就需要使用若干个成员运算符“.”找到最低一级的成员,对其进行赋值、存取以及运算操作。

例如,对上面定义的 student1 变量中的出生日期进行赋值:
student1.birthday.year=1986;
student1.birthday.month=12;
student1.birthday.day=6;
注意,不能使用 student1.birthday 访问 student1 变量中的成员 birthday,因为 birthday 本身也是一个结构体变量。

结构体变量的成员可以像普通变量一样,进行各种运算。例如:
product2.iPrice=product1.iPrice+500;
product1.iPrice++;
因为“.”运算符的优先级最高,所以 product1.iPrice++ 是 product1.iPrice 成员进行自加运算,而不是先对 iPrice 进行自加运算。

还可以对结构体变量成员的地址进行引用,也可以对结构体变量的地址进行引用,例如:
scanf("%d", &product1.iPrice);  /* 输入成员 iPrice 的值 */
printf("%o", &product1);        /* 输出 product1 的首地址 */

【实例】展示老师基本信息。先定义一个表示老师的结构体,成员包括姓名、年龄和教龄;然后在主函数中使用该结构体定义一个老师,先赋值,再输出。
#include "stdio.h"
#include <string.h>
struct Teacher
{
    char name[64];    /* 姓名 */
    int age;         /* 年龄 */
    int seniority;   /* 教龄 */
};

int main()
{
    struct Teacher a_teacher;  /* 定义结构体变量 */
    strcpy(a_teacher.name, "zhangsan");  /* 将姓名复制给结构体变量 */
    a_teacher.age = 35;        /* 年龄 */
    a_teacher.seniority = 10;  /* 教龄 */
    printf("姓名:%s\n", a_teacher.name);
    printf("年龄:%d\n", a_teacher.age);
    printf("教龄:%d\n", a_teacher.seniority);
    return 0;
}
运行程序,结果为:

姓名:zhangsan
年龄:35

教龄:10
先声明结构体类型 Teacher,以表示老师这种特殊的类型,在结构体中定义了有关的成员。

在主函数 main() 中使用 struct Teacher 定义结构体变量 a_teacher,然后根据赋值的信息,引用结构体变量 a_teacher 中的成员,使用 printf() 函数将其进行输出显示。

C语言结构体变量的初始化

结构体类型与其他基本类型一样,也可以在定义结构体变量时指定初始值。例如:
struct Student
{
    char cName[20];
    char cSex;
    int iGrade;
} student1={"HanXue",'W',3};  /* 定义结构体变量并设置初始值 */
定义的变量后面使用等号,初始化值放在大括号中,数据顺序与结构体的成员列表顺序一致。

【实例】输出新来学生信息。本实例演示了两种初始化结构体的方式,一种是在声明结构体及定义变量的同时进行初始化,另一种是在定义结构体变量后进行初始化。
#include <stdio.h>
struct Student
{
    char cName[20];    /* 姓名 */
    char cSex;        /* 性别 */
    int iGrade;       /* 年级 */
} student1={"HanXue",'W',3};  /* 方式 1:定义结构体时,直接赋初始值 */

int main()
{
    struct Student student2={"WangJiaSheng",'M',3};  /* 方式 2:后续再定义变量并赋初始值 */
    printf("第一个学生信息:\n");
    printf("姓名: %s\n", student1.cName);
    printf("性别: %c\n", student1.cSex);
    printf("年级: %d\n", student1.iGrade);
    printf("第二个学生信息:\n");
    printf("姓名: %s\n", student2.cName);
    printf("性别: %c\n", student2.cSex);
    printf("年级: %d\n", student2.iGrade);
    return 0;
}
声明结构体时定义 student1 并对其初始化,待赋值内容放在后面大括号中,每个数据都与结构体的成员数据相对应。

在 main() 函数中使用声明的结构体类型 struct Student 定义变量 student2,并且进行初始化的操作。

最后将两个结构体变量中的成员进行输出,并比较二者数据的区别。运行程序,结果为:

第一个学生信息:
姓名: HanXue
性别: W
年级: 3
第二个学生信息:
姓名: WangJiaSheng
性别: M
年级: 3

注意,并不是所有的结构体成员都可以赋值,如果某个成员使用 const 做了限定,就不可以再对其赋值。

相关文章