3.5 结构体
在一些复杂的系统程序中,仅有一些基本类型(如字符型、整型和浮点型等)的数据是不够的,有时需要将一些各种类型的变量放在一起,形成一个组合形变量,即结构体变量(structure,又称结构或结构体)。
结构体(structure)是C语言应用比较多的一种数据结构,它可以有效地将各种数据(包括各种不同类型的数据)整合到一个数据体中,可以更好地实现程序的结构化,更方便地管理数据及对数据的操作。
在嵌入式系统开发中,一方面由于系统资源严重不足,另一方面由于各种变量相互通信、相互作用,所以正确合理使用结构体不仅可以为系统节约一部分宝贵的资源,而且可以简化程序的设计,使软件设计的可读性和可维护性都大大增强。
1.结构体的定义和引用
结构体的定义和引用主要有以下三个步骤。
1)定义结构体的一般形式结构体是一种构造类型,它由若干成员组成,每一成员可以是一个基本数据类型或者是一个构造类型。定义一个结构类型的一般形式为
struct 结构体名 { 结构体成员说明 };
结构体成员说明用来描述结构体由哪些成员组成,且每个成员必须做类型说明。结构体成员说明的格式为
类型标识符 成员名;
成员名的命名应符合标识符的命名规则,在同一结构体中不同分量不允许使用相同的名字。例如,定义一个名为stu的结构类型:
struct stu { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 };
在上述定义中,“struct stu”表示这是一个结构体类型,结构体名为“stu”。在该结构体中包含了7个结构体成员:int num,char name[30],int age,long number,char sex,float secore[7]和char address[50]。在这7个结构体成员中,第1个和第3个成员为整型变量;第2个和最后一个成员为字符数组;第4个为长整型变量;第5个为字符变量;第6个为浮点型数组。注意,struct stu是程序开发人员自己定义的结构类型,它和系统定义的标准类型(如int、char和float等)一样可以用来定义变量的类型。
2)定义结构体类型变量上面定义的stuct student只是结构体的类型名,而不是结构体的变量名。为了正常执行结构体的操作,除了定义结构体的类型名外,还需要进一步定义该结构类型的变量名。定义一个结构体的变量名时,可采用以下3种方法进行。
方法一:先定义结构体,再声明结构体变量。
这种形式的定义格式如下:
struct 结构体名 { 结构体成员说明 };
定义好一个结构体后,就可以用它来定义结构体变量了。一般格式如下:
struct 结构体名 变量名1,变量名2,变量名3,…,变量名n;
例如:
struct stu { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 }; struct stu student1,student2; //定义结构体类型变量student1和student2 struct stu student3,student4; //定义结构体类型变量student3和student4
在该例中,在定义了结构的类型struct stu之后,使用“struct stu student1,student2”和“struct stu student3,student4”定义的student1、student2、student3和student4即为struct stu类型的结构体变量。
方法二:在定义结构体类型的同时定义该结构体变量。
这种形式的定义格式如下:
struct 结构体名 { 结构体成员说明 }变量名1,变量名2,变量名3,…,变量名n;
例如:
struct stu { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 }student1,student2,student3,student4;
也可以再定义更多的该结构体类型变量:
struct stu student5,student6;
方法三:直接定义结构体类型变量。这种形式的定义格式如下:
struct { 结构体成员说明 }变量名1,变量名2,变量名3,…,变量名n;
例如:
struct { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 }student1,student2,student3,student4;
在上述3种方法中,都声明了student1、student2、student3和student4这4种变量,这些变量的类型完全相同,其中方法三与方法二的区别在于:方法三中省去了结构体名,而直接给出了结构体变量。
关于结构体有以下几点说明。
①结构体类型和结构体变量是两个不同的概念,对于一个结构体变量而言,在定义时一般先定义一个结构体类型,然后再定义该结构体变量为该种结构体类型。
②在定义一个结构体类型时,结构体名不占用任何存储空间,也不能对结构体名进行赋值、存取的运算,只是给出该结构的组织形式。结构体变量是一个结构体中的具体组织成员,编译器会给该结构体变量分配确定的存储空间,因此可以对结构体变量名进行赋值、存取和运算。
③结构体的成员也可以是一个结构变量,它可以单独使用,其作用与地位相当于普通变量的作用与地位。
④结构体成员可以与程序中的其他变量名相同,但两者表示不同的含义。
⑤结构体可以嵌套使用,一个结构体中允许包含另一个结构体。
⑥如果在程序中使用的结构体数目较多、规模较大时,可以先将它们集中定义在一个头文件中,然后用宏指令“#include”将该头文件包含在需要它们的源文件中。
3)结构体类型变量的引用定义了一个结构体变量后,就可以对它进行引用,即对其进行赋值、存取的运算了。一般情况下,结构体变量的引用是通过对其成员的引用来实现的。结构体变量成员引用的一般格式如下:
结构体变量名.成员名;
其中,“.”是存取成员的运算符。例如:
student1.num=2010003; //学生1的学号 student1.age=12; //学生1的年龄
对结构体变量进行引用时,还应遵循以下规则。
①结构体不能作为一个整体参加赋值、存取和运算,也不能整体作为函数参数或函数的返回值。对结构体所执行的操作,只能用“&”运算符取结构体的地址,或对结构体变量的成员分别加以引用。
②如果一个结构体变量中的成员又是另一个结构体变量,即出现结构体嵌套时,则需要采用若干个成员运算符,一级一级地找到最低级的成员,而且只能对这个最低级的结构元素进行存取访问。例如:
student1.birthday.month=12; //学生1的生日月份(嵌套结构)
注意,在此例中不能用student1.birthday.来访问student1变量的成员birthday,因为birthday本身也是一个结构体类型变量。
③结构体类型变量的成员可以像普通变量一样进行各种运算。例如:
student1.age++;
2.结构体的初始化
和其他类型的变量一样,对结构体类型的变量也可以在定义时赋初值进行初始化。例如:
struct { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 }; struct stu student1={2010003,“LiPing”,12,43010119981203126,’M’,{89,86,95,90, 77,94,68},“湖南长沙”}; struct stu student2={2010004,“WangQian”,11,43010119990906123,’W’,{80,86,95, 87,79,96,77},“湖南长沙”}; struct stu student3={2010005,“TianMinQin”,14,43010119960725122,’M’,{79,80,65, 83,77,94,78},“湖南长沙”}; struct stu student4={2010006,“ChenLei”,13,43010119971116127,’W’,{89,84,59,87, 68,91,65},“湖南长沙”};
3.结构体数组
如果数组中的每个元素都具有相同结构类型的结构体变量,则称该数组为结构体数组。结构体数组与变量数组的不同在于:结构体数组的每一个元素都是具有同一个结构体类型的结构体变量;它们都具有同一个结构体类型,都含有相同的成员项。
1)结构体数组的定义结构体数组的定义和结构体变量的定义方法类似,只需说明其为数组即可。例如:
struct stu { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 }; struct stu student[4];
以上定义了一个数组student,其元素为struct stu类型数据,数组有4个元素。也可直接定义一个结构体数组,如:
struct stu { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 }student[4];
或
struct { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 }student[4];
2)结构体数组的初始化结构体数组也可以在定义时赋初值,以进行初始化。例如:
struct stu { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 }student[4]={{2010003,“LiPing”,12,43010119981203126,’M’,{89,86,95,90,77, 94,68},“湖南长沙”},{2010004,“WangQian”,11,43010119990906123,’W’,{80, 86,95,87,79,96,77},“湖南长沙”},struct stu student3={2010005,“TianMinQin”, 14,43010119960725122,’M’,{79,80,65,83,77,94,78},“湖南长沙”},struct stu student4={2010006,“ChenLei”,13,43010119971116127,’W’,{89,84,59,87,68, 91,65},“湖南长沙”}};
4.指向结构体类型数据的指针
一个结构体变量的指针就是该变量所占据的内存中的起始地址。可以设一个指针变量,用来指向一个结构体数组,此时该指针变量的值就是结构体数组的起始地址。
1)指向结构体变量的指针当一个指针变量用来指向一个结构体变量时,称之为结构体指针变量。结构体指针与数组指针、函数指针的情况相同,它的值是所指向的结构体变量的首地址。通过结构体指针就可以访问该结构体变量了。指向结构体变量的指针变量的一般形式为
struct 结构体类型名 *指针变量名;
或者
struct { 结构体成员说明 }*指针变量名;
例如:
struct stu { int num; //定义学生的学号 char name[30]; //定义学生的姓名 int age; //定义学生的年龄 long number; //定义学生的身份证号码 char sex; //定义学生的性别 float secore[7]; //定义学生的7科考试成绩 char address[50]; //定义学生的家庭地址 }; struct stu *person;
在上述例子中定义了一个stu结构体的指针变量person。结构体指针变量在使用之前必须先对其进行赋初值。赋值时只能将结构体变量的首地址赋予该指针变量,不能将结构体名赋予该指针变量。
2)指向结构体数组的指针指针变量可以指向数组,同样指针变量也可以指向结构体数组及其元素。指向结构体数组的指针变量的一般形式如下:
struct 结构体数组名 *结构体数组指针变量名;
或者
struct { 结构体成员说明 }*结构体数组指针变量名[];