价值数万元单片机-第四部分机器人光盘1c语言第18章结构体_第1页
价值数万元单片机-第四部分机器人光盘1c语言第18章结构体_第2页
价值数万元单片机-第四部分机器人光盘1c语言第18章结构体_第3页
价值数万元单片机-第四部分机器人光盘1c语言第18章结构体_第4页
价值数万元单片机-第四部分机器人光盘1c语言第18章结构体_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第18章 结构体通过本章的学习中,要重点掌握以下知识点:结构体的概念及用途;结构体类型的声明及其字长;结构体变量的定义、访问和赋值;结构体数组和结构体指针的使用。18.1 结构体结构体(struct)在C语言中用于处理多个单一数据组成的数据集合。在复杂的数据处理中,结构体是必不可少的。结构体的使用是C语言编程的一个重要部分。本节将先讨论结构体的概念,再介绍如何定义结构体变量,最后使用范例来说明结构体的字节长度。18.1.1 结构体类型的概念结构体是指包含多个单一数据的数据集合。在一些应用中,需要处理的数据往往是若干个单一数据的集合。例如,一个完整的个人信息往往需要包含姓名、年龄、性别、职业、地

2、址、电话等信息。如果使用之前学习的简单数据类型来表示时间信息,就至少需要使用6个变量来实现,每次使用的时候都要访问至少6个变量,这是一个相当烦琐的过程。18.1.1 结构体类型的概念C语言中提供了结构体数据类型作为一个集合来处理这种复杂数据,一个结构体可以将多个单一信息结合在一起作为一个整体来使用。使用结构体时,首先要声明需要的结构体类型,其一般形式如下:struct 结构体名 数据类型1 结构体成员1;数据类型2 结构体成员2;数据类型3 结构体成员3;/* 分号不可缺少 */18.1.1 结构体类型的概念结构体名相当于这个结构体的标记,它与标识符struct共同组成这个结构体的名称。每一个

3、结构体可以包含很多成员,每一个成员都有一个数据类型,这些成员可以被声明为除该结构体类型本身外的任意有效数据类型。例如,对于上述的时间信息,可以声明如下的结构体类型来处理。18.1.1 结构体类型的概念01struct personal_infor 02char nameSIZE_N;/* 姓名 */03int age;/* 年龄 */04char gender; /* 性别 */05char professionSIZE_P; /* 职业 */06char addressSIZE_A; /* 地址 */07char telephoneSIZE_T; /* 电话 */08;/* 分号不可省略 *

4、/18.1.1 结构体类型的概念这个结构体包含了6个结构体成员,需要注意的是,这个数据类型的名称为struct personal_infor,而不是personal_infor。此外,这时得到的只是一个数据类型,要处理数据还要定义这种类型的变量。18.1.2 定义结构体变量声明了结构体类型后,便可以使用该类型来定义结构体变量。C语言中定义结构体变量有三种形式,其实这也是声明结构体类型的三种形式:注意:本节的结构体类型声明中的成员列表声明都与第18.1.1节中的struct personal_infor一样。18.1.2 定义结构体变量1声明结构体类型,并定义结构体变量例如,如果要定义perso

5、nal_infor结构体变量,可以使用如下代码:01struct personal_infor /* 声明结构体数据类型 */02char nameSIZE_N;/* 姓名 */03int age;/* 年龄 */04char gender; /* 性别 */05/* 省略 */06;07struct personal_infor Raul, Philip;/* 定义结构体变量 */08struct personal_infor Joe;/* 再定义一个变量 */18.1.2 定义结构体变量这种形式的定义方式可以多次定义结构体变量,如上第7行定义了Raul,在第8行可以再次使用该数据类型名来定

6、义另一个变量Joe。需要注意的是,必须同时使用标识符struct和结构体名来定义结构体变量,如下定义语句是错误的:personal_infor Erie;/* 错误 */这种形式也可以在声明结构体类型的同时定义结构体变量,如下所示。01struct personal_infor /* 声明结构体数据类型 */02char nameSIZE_N;/* 姓名 */03int age;/* 年龄 */04char gender; /* 性别 */05/* 省略 */06 Raul, Philip;/* 定义两个结构体变量 */07struct personal_infor Joe;/* 再定义一个变

7、量 */18.1.2 定义结构体变量2不声明结构体类型,直接定义结构体变量这种形式的定义语句如下:01struct /* 声明结构体数据类型 */02char nameSIZE_N;/* 姓名 */03int age;/* 年龄 */04char gender; /* 性别 */05/* 省略 */06 Raul, Philip, Joe;/* 定义三个结构体变量 */18.1.2 定义结构体变量3使用typedef得到简化的结构体类型名,再定义结构体变量由于结构体数据类型的名字由标识符和结构体名两部分组成,书写起来名字较长,因此常常使用typedef来简化其数据类型名字,如下所示。18.1.

8、2 定义结构体变量01typedef struct _personal_infor/* 声明结构体数据类型 */02char nameSIZE_N;/* 姓名 */03int age;/* 年龄 */04char gender; /* 性别 */05/* 省略 */06 personal_infor;18.1.2 定义结构体变量也可以省略该结构体名,如下所示。01typedef struct /* 声明结构体数据类型 */02char nameSIZE_N;/* 姓名 */03int age;/* 年龄 */04char gender; /* 性别 */05/* 省略 */06 persona

9、l_infor;得到简化的结构体数据类型名后,便可以与其他简单数据类型一样来定义结构体变量,如下所示。personal_infor Raul, Philip;personal_infor Joe;18.1.2 定义结构体变量需要注意的是,如果要在结构体内定义本指向本结构体类型空间的指针时,只能使用第一种形式,例如:01typedef struct _personal_infor/* 声明结构体数据类型 */02char nameSIZE_N;/* 姓名 */03int age;/* 年龄 */04char gender; /* 性别 */05/* 省略 */06struct _personal

10、_infor * next;/* 声明一个指向本结构体类型空间的指针 */07 personal_infor;18.1.3 结构体的字节长度一般的系统中,为了寻址的方便,数据在内存中存储时一般以其本身数据类型的字节长度为基本单位对齐。例如,int型在内存中是以sizeof(int)个字节对齐的,char型在内存中是以sizeof(char)个字节对齐的。而结构体数据在存储时是以其中字节长度最大的成员的字节数为基本单位对齐的。18.1.3 结构体的字节长度注意:所谓对齐,是指将内存以一个固定的字节数作为最小单位分块,分配内存时只能一块一块地分配。例如,以4字节对齐,就是将整个内存4个字节4个字节

11、地分块,分配内存时只能4个字节4个字节地分。可以使用#pragma pack预处理命令来改变对齐规则,由于篇幅限制,在此不多做介绍。18.1.3 结构体的字节长度结构体中地成员分配的内存空间是相邻的。结构体变量所占的字节空间数,即结构体数据类型的字节长度,一般等于各个结构体成员的字节长度和。例如:struct data_type int a;int b;int c;18.1.3 结构体的字节长度但是当相邻地结构体成员的字节长度长短不一时,由于内存对齐的影响,会使结构体额外占用一些空间,从而使其内存空间大于各个结构体成员的字节长度总和。18.1.3 结构体的字节长度数据类型data_type_A

12、的字节长度为12个字节。data_type_A的内存分布如下图所示。18.1.3 结构体的字节长度v的内存分布如下图所示。18.1.3 结构体的字节长度v的内存分布如下图所示。 18.2 结构体的使用结构体变量的使用与之前学习过的一般变量的使用略有不同。定义一个结构体变量后,不能直接对结构体变量进行操作,要访问结构体的内存空间,必须通过访问其成员来实现。本节将先讨论如何访问结构体成员,再介绍初始化结构体变量的方法,最后分析浅复制和深复制的原理、两者的区别以及需要注意的问题。18.2.1 访问结构体成员使用成员操作符(.)可以访问结构体成员。成员操作符是一个二元操作符,前面的操作符为结构体变量,

13、后面的操作符为结构体成员名。其标准形式如下:结构体名.结构体成员名;例如,要访问Raul的信息,可以使用如下表达式:01R/* 访问Raul的姓名 */02Raul.age/* 访问Raul的年龄 */03Raul.gender/* 访问Raul的性别*/0418.2.2 初始化结构体变量使用结构体变量和其他类型变量一样,在使用前最好对其初始化。为结构体初始化的方法与数组初始化类似,可以使用一个数值序列依次为结构体成员赋值。例如为范例18-2中的raul变量初始化的语句可以如下:per_infor raul = “Raul Wang”, 25, M;该语句依次将raul的第一个

14、成员char型数组name赋值为”Raul Wang”,第二个成员int型变量age赋值为25,将第三个成员char型变量gender赋值为M。18.2.2 初始化结构体变量也可以只初始化结构体变量的部分成员。此时,与初始化数组元素类似,必须对结构体变量的前面的成员连续初始化,未被初始化的成员都被自动清零,如下所示。per_infor raul = “Raul Wang”;这样,raul的name成员被初始化为“Raul Wang”,而未被初始化的age成员和gender成员的内存空间都被清零,即age等于0,gender等于0。如果要将结构体变量清零,只需将其第一个成员内存初始化为全零即可。

15、例如:per_infor raul = 0;18.2.3 浅复制和深复制结构体变量之间可以直接赋值。以范例18-3中的data_t结构体为例:01data_t a = 2, 2.0, c, “DATA”;02data_t b = a;18.2.3 浅复制和深复制第2行语句会将b赋值为a,该赋值过程为将a的内存内容按字节依次复制给b。因此,赋值后的b的各个成员的值与a完全相同。这种按内存空间内容复制的方式为浅复制。一般情况下,浅复制的方式不会有什么问题。但是,如果结构体中含指针型成员的话,就会存在安全隐患,例如:01typedef struct _data 02int a;03int * p;0

16、4 data_t;05int x = 2;06data_t a = 12, &x;07data_t b = a;18.2.3 浅复制和深复制所谓深复制,是指如果结构体含有指针型成员,复制时不是简单地复制该成员的值,而是先为该指针成员申请新的内存空间,再复制其指向的空间的内容。这样复制后新的结构体便得到一个独立的内存空间。一般来说,深度复制函数有两个部分:复制非指针成员部分和复制指针成员部分。18.3 结构体数组结构体数组就是以结构体类型为数组元素的数组。当处理一组类似个人信息之类的复杂数据时,常常需要用到结构体数组。本节先介绍定义结构体数组的方法,再介绍如何初始化结构体数组,最后通过范例来演示

17、结构体数组的使用。18.3.1 定义结构体数组与定义结构体变量的方式相对应,定义结构体数组的方法也有三种,如下所示。18.3.1 定义结构体数组1声明结构体类型,并定义结构体数组可以声明一个结构体类型后,再使用该结构体类型来定义结构体数组,如下所示。struct person_infor /* 定义结构体数组worker */char name20;int age;char gender; worker10; /* 定义结构体数组worker */struct person_infor farmer10; /* 定义结构体数组farmer */18.3.1 定义结构体数组2不声明结构体类型,直

18、接定义结构体数组也可以直接定义结构体数组,如下所示。struct char name20;int age;char gender; worker10; /* 定义结构体数组worker */18.3.1 定义结构体数组3使用typedef还可以先使用typedef来得到结构体类型的别名,再使用该别名来定义结构体数组,如下所示。typedef struct _person_infor /* 结构体名可以省略 */char name20;int age;char gender; person_infor;person_infor worker10; /* 定义结构体数组worker */perso

19、n_infor farmer10; /* 定义结构体数组farmer */18.3.2 初始化结构体数组初始化结构体数组可以采用初始化值序列的形式,由于结构体本身有多个成员,因此其值序列与二维数组的初始化值序列有些类似。18.3.2 初始化结构体数组形式如下:01struct person_infor /* 声明结构体struct person_infor */02char name20;03int age;04char gender;05 student4 = /* 定义含有4个结构体数据的student数组 */06“Raul”, 25, M,/* 初始化第一个结构体元素 */07“Joe

20、”, 23, F,/* 初始化第二个结构体元素 */08“Philip”, 21, M,/* 初始化第三个结构体元素 */09“William”, 22, M/* 初始化第四个结构体元素 */10;18.3.2 初始化结构体数组上述第69行为初始化值序列。其中,每行都有一对花括弧,其中均包含3个数据,用来初始化一个数组元素,即一个结构体变量。同样与其他类型数组类似,可以只初始化部分数组元素,例如:01struct person_infor /* 声明结构体struct person_infor */02char name20;03int age;04char gender;05 student

21、10 = /* 定义含有10个结构体数据的student数组 */06“Raul”, 25, M,/* 初始化第一个结构体元素 */07“Joe”, 23, F,/* 初始化第二个结构体元素 */08“Philip”,/* 初始化第三个结构体元素 */09“William” /* 初始化第四个结构体元素 */10;18.3.2 初始化结构体数组上述语句定义了含有10个数组元素的结构体数组,但只显式初始化了4个,剩余的数组元素的内存都被自动初始化为0。其中,第8行和第9行的结构体元素的初始化序列都只包含1个字符串,那么该结构体元素的剩余空间也被自动初始化为0。也可以不指定数组容量,则其数组容量由

22、初始化列表的值的个数来决定,如下所示。01struct person_infor /* 声明结构体struct person_infor */02char name20;03int age;04char gender;05 student = /* 定义student数组 */06“Raul”, 25, M,/* 初始化第一个结构体元素 */07“Joe”, 23, F,/* 初始化第二个结构体元素 */08“Philip”,/* 初始化第三个结构体元素 */09“William” /* 初始化第四个结构体元素 */10;18.3.2 初始化结构体数组由于数组初始化序列中含有4个结构体值,因此

23、该student数组的数组容量为4。另外,还可以将所有初始化值序列放在同一个花括弧内,例如:01struct person_infor 02char name20;03int age;04char gender;05 student4 = /* 定义含有4个结构体数据的student数组 */06“Raul”, 25, M,/* 初始化第一个结构体元素 */07“Joe”, 23, F,/* 初始化第二个结构体元素 */08“Philip”, 21, M,/* 初始化第三个结构体元素 */09“William”, 22, M/* 初始化第四个结构体元素 */10;18.3.3 结构体数组使用举例下面演示如何使用结构体数组来处理人物信息,并输出最年轻男性的人物信息。18.4 结构体指针结构体指针是使用结构体编程的重要内容。声明一个结构体指针变量,再将该变量初始化为一个存储结构体数据的内存空间的首地址后,便可以使用这

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论