基于Proteus的AVR单片机C语言程序设计与仿真
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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
            {
            结构体成员说明
            }*结构体数组指针变量名[];