首页 > 编程笔记

C语言结构体(struct)的定义、初始化和使用

结构体类型是一种由用户根据实际需要自己构造的数据类型,所以必须要“先定义,后使用”。也就是说,用户必须首先构造一个结构体类型,然后才能使用这个结构体类型来定义变量。

C语言结构体类型的定义

结构体类型是一种构造数据类型,它由若干个互相有关系的“成员”组成,每一个成员的数据类型可以相同,也可以不同。对每个特定的结构体都需要根据实际处理的对象进行数据项的定义,也就是构造,以明确该结构体的成员及其所属的数据类型。

C语言中提供的定义结构体类型的语句格式为:

struct 结构体类型名
{
   数据类型1  成员名1;
   数据类型2  成员名2;
         …
   数据类型n  成员名n;
};

其中,struct 是C语言中的关键字,表明是在进行一个结构体类型的定义。结构体类型名是一个合法的C语言标识符,对它的命名要尽量做到“见名知意”。

比如,描述一个学生的信息可以用“student”,描述一本图书的信息可以使用“bookcard”等。由定义格式可以看出,结构体数据类型由若干个数据成员组成,每个数据成员可以是任意一个数据类型,最后的分号表示结构体类型定义的结束。

例如,定义一个学生成绩的结构体数据类型如下:
struct student
{
   char no[8];       /*学号*/
   char name[8];  /*姓名*/
   float eng;   /*英语成绩*/
   float math;   /*数学成绩*/
   float ave ;   /*平均成绩*/
};
在这个结构体中有 5 个数据成员,分别是 no、name、eng、math 和 ave,前 2 个是字符数组,分别存放学生的学号和姓名信息;eng、math、ave 是单精度实型,分别存放英语、数学以及平均成绩。

【示例1】结构体可以嵌套定义,即一个结构体内部成员的数据类型可以是另一个已经定义过的结构体类型。代码如下:
struct date
{
  int year;
  int month;
  int day;
};
struct student
{
  char name[10];
  char sex /* 定义性别,m 代表男,f 代表女*/;
  struct date birthday;
  int age;
  float score;
};
在这个代码段中,先定义了一个结构体类型 date,然后在定义第 2 个结构体类型时,其成员 birthday 被声明为 date 结构体类型。这就是结构体的嵌套定义。

提示:在定义嵌套的结构类型时,必须先定义成员的结构类型,再定义主结构类型。

关于结构体的说明如下。

C语言结构体变量的定义

结构体类型的定义只是由用户构造了一个数据类型,定义结构体类型时系统并不为其分配存储空间。结构体类型定义好后,可以像C中提供的基本数据类型一样被使用,即可以用它来定义变量,称为结构体变量,系统会为该变量分配相应的存储空间。

在C语言中,定义结构体类型变量的方法有以下 3 种。

1) 先定义结构体类型,后定义变量

例如,先定义一个结构体类型。
struct student
{
  char no[8] ; /* 学号*/
  char name[8]; /* 姓名*/
  float eng; /* 英语成绩*/
  float math; /* 数学成绩*/
  float ave ; /* 平均成绩 */
};
我们可以用定义好的结构体类型 student 来定义变量,该变量就可以用来存储学生的信息了。定义如下。

struct student stu[30]; /* 定义结构体类型的数组*/

这里定义了一个包含 30 个元素的数组 stu,每个数组元素都是一个结构体类型的数据,可以保存 30 个学生的信息。例如:

struct student stu1; /* 定义一个结构体类型的变量*/

说明:当一个程序中多个函数内部需要定义同一结构体类型的变量时,应将结构体类型定义为全局类型。

2) 定义结构体类型的同时定义变量

语法形式如下。

struct 结构体标识符
{
  数据类型1 成员名1;
  数据类型2 成员名2;
    …
  数据类型n 成员名n;
} 变量1, 变量2, … , 变量n;

其中,“变量1,变量2,…,变量n”为变量列表,遵循变量的定义规则,彼此之间通过逗号分隔。

说明:在实际应用中,定义结构体的同时定义结构体变量适合于定义局部使用的结构体类型或结构体类型变量,例如在一个文件内部或函数内部。

3) 直接定义结构体类型变量

这种定义方式是不指出具体的结构体类型名,而直接定义结构体成员和结构体类型的变量。此方法的语法形式如下。

struct
{
  数据类型1 成员名1;
  数据类型2 成员名2;
    …
  数据类型n 成员名n;
} 变量1, 变量2, … , 变量n;

这种定义的实质是先定义一个匿名结构体,之后再定义相应的变量。由于此结构体没有标识符,所以无法采用定义结构体变量的第 1 种方法来定义变量。

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

定义结构体变量的同时就对其成员赋初值的操作,就是对结构体变量的初始化。

结构体变量的初始化方式与数组的初始化类似,在定义结构体变量的同时,把赋给各个成员的初始值用{}括起来,称为初始值表,其中各个数据以,分隔。具体形式如下。

struct 结构体标识符
{
  数据类型1 成员名1;
  数据类型2 成员名2;
   …
  数据类型n 成员名n;
} 变量名={ 初始化值1, 初始化值2, … , 初始化值n };

【示例2】结构体变量的初始化代码如下:
struct student
{
  char name[10]; /* 学生姓名*/
  char sex; /* 定义性别,m 代表男,f 代表女*/
  int age; /* 学生年龄*/
  float score; /* 分数*/
} stu[30], stu1 = {"zhangsan", 'm', 20, 88.8}, stu2;
struct student
{
  char name[10]; /* 学生姓名*/
  char sex; /* 定义性别,m 代表男,f 代表女*/
  int age; /* 学生年龄*/
  float score; /* 分数*/
} stu[30], stu1 = {"zhangsan", 'm', 20, 88.8}, stu2;

本例在定义结构体类型 student 的同时定义了结构体数组和两个结构体变量,并对变量 stu1 进行了初始化,变量 stu1 的 4 个成员分别得到了一个对应的值,即 name 为“zhangsan”,sex 为“m”,age 为“20”,score 为“88.8”,这样,变量 stu1 中就存放了一个学生的信息。

C语言结构体变量的引用

结构体变量的引用分为结构体变量成员的引用和结构体变量本身的引用两种。

1) 结构体变量成员的引用

结构体变量包括一个或多个结构体成员,引用其成员的语法格式如下。

结构体变量名.成员名;

其中,.是专门的结构体成员运算符,用于连接结构体变量名和成员名,属于高级运算符,结构成员的引用表达式在任何地方出现都是一个整体,如 stu1.age、stu1.score 等。

【示例2】嵌套的结构体定义中成员的引用也一样。如下代码:
struct date
{
  int year; /* 年*/
  int month; /* 月*/
  int day; /* 日*/
};
struct student
{
  char name[10];
  char sex;
  struct date birthday;
  int age;
  float score;
}stu1;

其中,结构体变量 stu1 的成员 birthday 也是一个结构体类型,这是嵌套的结构体定义。对该成员的引用,要用结构体成员运算符进行分级运算。也就是说,对成员birthday 的引用是这样的:stu1.birthday.year,stu1.birthday.month,stu1.birthday.day

结构体成员和普通变量的使用一样,比如,可以对结构体成员进行赋值操作,下列代码都是合法的。
scanf("%s",stu1.name);
stu1.sex='m';
stu1.age=20;
stu1.birthday.year=1999;

2)结构体变量本身的引用

结构体变量本身的引用是否遵循基本数据类型变量的引用规则呢?我们先来看一下对结构体变量的赋值运算。
struct student
{
  char name[10];
  char sex;
  int age;
  float score;
};
struct student stu1={"zhangsan",'m',20,88.8},stu2;
C语言规定,同类型的结构体变量之间可以进行赋值运算,因此这样的赋值是允许的。例如:

stu2=stu1;

此时,系统将按成员一一对应赋值。也就是说,上述赋值语句执行完后,stu2 中的 4 个成员变量分别得到 zhangsan、m、20 和 88.8。

但是,在C语言中规定,不允许将一个结构体变量作为整体进行输入或输出操作。因此以下语句是错误的。

scanf("%s,%d,%d,%f",&stu1);
printf("%s,%d,%d,%f",stu1);

将结构体变量作为操作对象时,还可以进行以下两种运算。

①用 sizeof 运算符计算结构体变量所占内存空间。

定义结构体变量时,编译系统会为该变量分配内存空间,结构体变量所占内存空间的大小等于其各成员所占内存空间之和。

C中提供了sizeof运算符来计算结构体变量所占内存空间的大小,其一般使用形式如下。

sizeof( 结构体变量名)

或者:

sizeof( 结构体类型名)

②用 & 运算符对结构体变量进行取址运算。

我们应该知道普通变量的取址,例如,&a 可以得到变量 a 的首地址。对结构体变量的取址运算也是一样的,例如,定义一个结构体变量 stu1,那么利用 &stu1 就可以得到 stu1 的首地址。

优秀文章