第9章 结构体、共用体和枚举类型
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第9章 结构体、共用体和枚举类型
9.1 结构体类型与结构体变量 9.2 结构体数组 9.3 向函数传递结构体型数据 9.4 链表 9.5 共用体 9.6 枚举类型 9.7 用户自定义类型
9.1 结构体类型与结构体变量
• 结构体类型的定义
–概述:
• 建立单链表的主要步骤为:
– 生成只含有头结点的空链表; – 然后读取数据信息,生成新结点,将数据存放于新结点中, 插入新结点到单链表中 – 重复第二步,直到输入结束。 根据新结点插入到链表的位置的不同,建立链表的方式, 分为在表尾插入的方法和在表头插入的方法。 •表尾插入: 例9.6 •表头插入: 例9.7
• 共用体变量的定义
–用已定义的共用体类型去定义共用体变量 –定义共用体类型的同时定义变量: –定义无名共用体类型的同时定义变量:
• 共用体变量的引用
–引用方式:共用体变量名.成员名 共用体变量名. 共用体变量名 –说明: 对于共用体变量,只能引用它的成员,而不能引用整个 共用体变量。若共用体的成员是构造类型的,则需要逐级引 用至最低级的成员。 –能通过定义指向共用体的指针变量来引用共用体变量。
在实际应用中,一组相关的数据可能是不同类型的。C语 言提供了包含不同类型成员的类型来定义这样的数据,这 种类型就是结构体类型 结构体类型。 结构体类型
– 定义形式:
struct 结构体名 类型名1 成员名1 {类型名1 成员名1; 类型名2 成员名2 类型名2 成员名2; …… 类型名n 成员名n 类型名n 成员名n; };
• 举例
例9.11 上一页
9.6 枚举类型
• 枚举类型的定义–定义来自式:enum 枚举类型名{枚举常量1,枚举常量2,……,枚举常量n}; •
枚举类型变量的定义和使用
– 定义方式:
• 用已定义的枚举类型去定义变量: • 也可以在定义枚举类型的同时定义变量: • 对于上种方式也可省略枚举类型名: – 引用: • 枚举类型变量的取值范围只能是其所枚举的各个常量。 • 枚举变量的比较相当于比较它们所隐含的整数值。 • 枚举类型变量的值是对应枚举常量所代表整数值。
上一页
• 在链表中插入结点
设指针变量s指向待插入结点,假设指定结点为p。 – 插入到指定结点之后: ① s−>next=p−>next; ② p−>next=s;
– 插入到指定结点之前:首先要找到p的前驱结点q。
例9.8
上一页
• 在链表中删除结点
在一个单链表中删除指定结点,首先要找到该结点的前驱结 点,然后修改前驱结点的指针域指向待删结点的后继结点,然 后释放被删结点。
上一页
9.4 链表
• 链表的特点
–链表是一种动态的进行存储分配的数据结构,程序执行中, 可以在需要时开辟存储单元,在不需要时释放存储单元。 –链表的结点包含数据域和链接域,数据域用来保存数据信 息,链接域用来保存该结点的后继结点或前驱结点的地址。 –一个链表用一个头指针来保存该链表的首地址,即第一个 结点的地址。头指针是一个链表的标志。
• 向函数传递结构体变量
函数调用时,形参也要占用内存空间,因此函数之间传递结 构体变量会带来时间和空间的巨大开销;而且,形参与实参之 间是“值传递”的方式,被调函数对形参结构体变量的修改并 不 能传递给实参,所以虽然语法上允许,但一般很少采用这种传 递方式。 首页 上一页
• 向函数传递结构体变量的地址
• 一个单链表的逻辑示意图
首页 上一页
• 创建链表
– 相关函数:
• malloc函数 1.原型:void *malloc(unsigned int size); 2.功能:在内存的动态存储区中分配size个字节的连续空间, 它的返回值是所分配的那一段空间的起始地址,若分配失 败,则返回一个空指针(0)。 • calloc函数 1.原型:void *calloc(unsigned int n,unsigned int size); 2.功能:内存的动态存储区中分配n个长度为size个字节的 连续空间,它的返回值是指向所分配空间的起始地址,若 分配失败,则返回一个空指针(0)。 • free函数 1.原型:void free(void *p); 2.功能:释放p所指向的内存区,该函数没有返回值。一般 p是调用malloc函数或calloc函数的返回值。 上一页
• 举例
例9.12 上一页
9.7 用户自定义类型
• 用户自定义类型的含义和格式
–含义:用户自定义类型是对已存在的标准类型或已定义
了的类型起一个新名字,而不是去定义原来没有的类型。
–步骤:
• 定义相应类型的变量; • 将变量名用新类型名替换; • 在最前面加上 typedef。 这样,一个新类型就声明了,可以用其去定义变量。
• 举例
例9.1 上一页
9.2 结构体数组
• 结构体数组的定义、初始化
– 结构体数组的定义: • 可以定义结构体类型后再定义数组; • 也可以在定义结构体类型的同时定义数组。 例如:struct student {int number; char name[8]; float score[3]; float ave; }stu[3]={{1001,"zhang",{80,78,67}}, {1002, "wang",{98,78,86}}, {1003, "li",{79,89,68}} }; 首页 上一页
• 结构体数组的引用
–引用形式1: 数组名[下标 成员名 数组名 下标].成员名 下标
• stu[1].number; 表示第1个学生的学号 • stu[0].score[2] ; 表示第0个学生的第2门课的成绩 –引用形式2: 通过指针引用结构体数组的元素及其成员 若已有前面的定义,ps指向stu[0],那么: • (*ps).number; 表示第0个学生的学号 • ps−>name; 表示第0个学生的姓名 • (++ps)−>ave; 表示先将指针ps向后移动,指向stu[1], 即该式表示第1个学生的平均成绩
– 注意:
• typedef只能声明类型名,不能用于定义变量。 • typedef和#define的区别: – 一是#define在预编译时处理,只是一种简单的替换; 而typedef在编译的时候处理,它并不是替换,是用 新类型名去定义变量。 – 二是#define是预处理命令,不能加分号;而typedef 是类型声明语句,以分号结束。 上一页
• 用typedef声明基本类型
– 形式: typedef 基本类型名 新类型名; 新类型名; 首页 上一页
• 用typedef声明构造类型
– 数组类型的声明
typedef 数据类型名 数组类型名[数组长度];
– 结构体类型的声明
typedef struct {类型名 成员名1; 类型名 成员名2; …… 类型名 成员名n; }结构体类型名;
– 注意
指向结构体变量的指针,与指向结构体变量的成员地指 针是不同类型的,它们之间不能直接相互赋值,则必须先进 行强制类型转换,转换为需要的类型,再赋值。
• 举例
例9.2 上一页
9.3 向函数传递结构体型数据
• 向函数传递结构体变量的成员
用结构体变量的成员作函数的实参,要注意作为实参的结构 体变量的成员的类型要与形参的类型相匹配。形参与实参之间 是“值传递”的方式。
例9.9
• 举例
例9.10
上一页
9.5 共用体
• 共用体类型的定义
–概述
共用体类型是由类型不同的、固定个数的成员所组成;所 有的共用体成员共占同一段内存,在微观上看,某一时刻 只能有某一个成员起作用,其它成员是不存在的。
– 定义形式:
union 共用体名 {类型名 成员名 ; 类型名1 类型名 成员名1; 类型名2 成员名2; 类型名 成员名 ; …… 类型名n 成员名n; 类型名 成员名 ; }; ; 首页 上一页
向函数传递结构体变量的地址是地址传递方式,被调函数中 可以通过实参传来的结构体变量的地址引用结构体变量,从而 在被调函数中对结构体变量的修改,也就间接的达到了改变主 调函数中的结构体变量的值的目的。 例9.3
• 向函数传递结构体数组
向函数传递结构体数组与传递其它的数组一样,实质上传递 的是数组的首地址,形参数组与实参数组共占内存单元。 例9.4
– 共用体类型的声明
typedef union {类型名 成员名1; 类型名 成员名2; …… 类型名 成员名n; }共用体类型名;
上一页
• 用户自定义类型的应用
– 应用:
• 对比较复杂且使用比较频繁的类型,可以用typedef声明 来简化程序的书写。 • 用typedef声明类型有助于提高程序的可移植性。
结构体数组stu的逻辑示意图为:
对于结构体类型的一维数组、二维数组,也可以定义指向 它们的指针变量,例如: struct student *ps=stu; 表示指针变量ps指向结构体数组stu的第0个元素,那么, ps+1表示stu[1]的地址,ps++表示指针向后移动一个元素的空 间,指向下一个元素。 上一页
首页 上一页
• 结构体变量的定义和初始化
– 结构体类型变量的定义方式:
• 用已经定义的结构体类型去定义结构体变量; • 定义结构体类型的同时定义结构体变量; • 定义无名结构体类型的同时定义结构体变量。
– 初始化:
可以在定义结构体变量的同时初始化。
– 说明:
• 定义结构体类型是说明一种由一些特定成员组成的模型。 模型并不是实体,变量才是占用内存的实体。 • 结构体变量的地址是结构体变量在内存的首地址,用来 存放结构体变量地址的变量是指向结构体的指针变量。 上一页
• 结构体变量的引用
–引用方式1: 结构体变量名.成员名 结构体变量名. –引用方式2: (*指针变量名).成员名 指针变量名)
或者是:指针变量名−>成员名 指针变量名−>成员名 指针变量名−> – 例:struct student {int number; char name[8]; int age; float score[3]; }stu={112, "wang",18,88,79,92},*ps=&stu; 那么对于变量stu的成员number的如下几种引用方式等效: ① stu.number;② (*ps).number;③ ps−>number;
9.1 结构体类型与结构体变量 9.2 结构体数组 9.3 向函数传递结构体型数据 9.4 链表 9.5 共用体 9.6 枚举类型 9.7 用户自定义类型
9.1 结构体类型与结构体变量
• 结构体类型的定义
–概述:
• 建立单链表的主要步骤为:
– 生成只含有头结点的空链表; – 然后读取数据信息,生成新结点,将数据存放于新结点中, 插入新结点到单链表中 – 重复第二步,直到输入结束。 根据新结点插入到链表的位置的不同,建立链表的方式, 分为在表尾插入的方法和在表头插入的方法。 •表尾插入: 例9.6 •表头插入: 例9.7
• 共用体变量的定义
–用已定义的共用体类型去定义共用体变量 –定义共用体类型的同时定义变量: –定义无名共用体类型的同时定义变量:
• 共用体变量的引用
–引用方式:共用体变量名.成员名 共用体变量名. 共用体变量名 –说明: 对于共用体变量,只能引用它的成员,而不能引用整个 共用体变量。若共用体的成员是构造类型的,则需要逐级引 用至最低级的成员。 –能通过定义指向共用体的指针变量来引用共用体变量。
在实际应用中,一组相关的数据可能是不同类型的。C语 言提供了包含不同类型成员的类型来定义这样的数据,这 种类型就是结构体类型 结构体类型。 结构体类型
– 定义形式:
struct 结构体名 类型名1 成员名1 {类型名1 成员名1; 类型名2 成员名2 类型名2 成员名2; …… 类型名n 成员名n 类型名n 成员名n; };
• 举例
例9.11 上一页
9.6 枚举类型
• 枚举类型的定义–定义来自式:enum 枚举类型名{枚举常量1,枚举常量2,……,枚举常量n}; •
枚举类型变量的定义和使用
– 定义方式:
• 用已定义的枚举类型去定义变量: • 也可以在定义枚举类型的同时定义变量: • 对于上种方式也可省略枚举类型名: – 引用: • 枚举类型变量的取值范围只能是其所枚举的各个常量。 • 枚举变量的比较相当于比较它们所隐含的整数值。 • 枚举类型变量的值是对应枚举常量所代表整数值。
上一页
• 在链表中插入结点
设指针变量s指向待插入结点,假设指定结点为p。 – 插入到指定结点之后: ① s−>next=p−>next; ② p−>next=s;
– 插入到指定结点之前:首先要找到p的前驱结点q。
例9.8
上一页
• 在链表中删除结点
在一个单链表中删除指定结点,首先要找到该结点的前驱结 点,然后修改前驱结点的指针域指向待删结点的后继结点,然 后释放被删结点。
上一页
9.4 链表
• 链表的特点
–链表是一种动态的进行存储分配的数据结构,程序执行中, 可以在需要时开辟存储单元,在不需要时释放存储单元。 –链表的结点包含数据域和链接域,数据域用来保存数据信 息,链接域用来保存该结点的后继结点或前驱结点的地址。 –一个链表用一个头指针来保存该链表的首地址,即第一个 结点的地址。头指针是一个链表的标志。
• 向函数传递结构体变量
函数调用时,形参也要占用内存空间,因此函数之间传递结 构体变量会带来时间和空间的巨大开销;而且,形参与实参之 间是“值传递”的方式,被调函数对形参结构体变量的修改并 不 能传递给实参,所以虽然语法上允许,但一般很少采用这种传 递方式。 首页 上一页
• 向函数传递结构体变量的地址
• 一个单链表的逻辑示意图
首页 上一页
• 创建链表
– 相关函数:
• malloc函数 1.原型:void *malloc(unsigned int size); 2.功能:在内存的动态存储区中分配size个字节的连续空间, 它的返回值是所分配的那一段空间的起始地址,若分配失 败,则返回一个空指针(0)。 • calloc函数 1.原型:void *calloc(unsigned int n,unsigned int size); 2.功能:内存的动态存储区中分配n个长度为size个字节的 连续空间,它的返回值是指向所分配空间的起始地址,若 分配失败,则返回一个空指针(0)。 • free函数 1.原型:void free(void *p); 2.功能:释放p所指向的内存区,该函数没有返回值。一般 p是调用malloc函数或calloc函数的返回值。 上一页
• 举例
例9.12 上一页
9.7 用户自定义类型
• 用户自定义类型的含义和格式
–含义:用户自定义类型是对已存在的标准类型或已定义
了的类型起一个新名字,而不是去定义原来没有的类型。
–步骤:
• 定义相应类型的变量; • 将变量名用新类型名替换; • 在最前面加上 typedef。 这样,一个新类型就声明了,可以用其去定义变量。
• 举例
例9.1 上一页
9.2 结构体数组
• 结构体数组的定义、初始化
– 结构体数组的定义: • 可以定义结构体类型后再定义数组; • 也可以在定义结构体类型的同时定义数组。 例如:struct student {int number; char name[8]; float score[3]; float ave; }stu[3]={{1001,"zhang",{80,78,67}}, {1002, "wang",{98,78,86}}, {1003, "li",{79,89,68}} }; 首页 上一页
• 结构体数组的引用
–引用形式1: 数组名[下标 成员名 数组名 下标].成员名 下标
• stu[1].number; 表示第1个学生的学号 • stu[0].score[2] ; 表示第0个学生的第2门课的成绩 –引用形式2: 通过指针引用结构体数组的元素及其成员 若已有前面的定义,ps指向stu[0],那么: • (*ps).number; 表示第0个学生的学号 • ps−>name; 表示第0个学生的姓名 • (++ps)−>ave; 表示先将指针ps向后移动,指向stu[1], 即该式表示第1个学生的平均成绩
– 注意:
• typedef只能声明类型名,不能用于定义变量。 • typedef和#define的区别: – 一是#define在预编译时处理,只是一种简单的替换; 而typedef在编译的时候处理,它并不是替换,是用 新类型名去定义变量。 – 二是#define是预处理命令,不能加分号;而typedef 是类型声明语句,以分号结束。 上一页
• 用typedef声明基本类型
– 形式: typedef 基本类型名 新类型名; 新类型名; 首页 上一页
• 用typedef声明构造类型
– 数组类型的声明
typedef 数据类型名 数组类型名[数组长度];
– 结构体类型的声明
typedef struct {类型名 成员名1; 类型名 成员名2; …… 类型名 成员名n; }结构体类型名;
– 注意
指向结构体变量的指针,与指向结构体变量的成员地指 针是不同类型的,它们之间不能直接相互赋值,则必须先进 行强制类型转换,转换为需要的类型,再赋值。
• 举例
例9.2 上一页
9.3 向函数传递结构体型数据
• 向函数传递结构体变量的成员
用结构体变量的成员作函数的实参,要注意作为实参的结构 体变量的成员的类型要与形参的类型相匹配。形参与实参之间 是“值传递”的方式。
例9.9
• 举例
例9.10
上一页
9.5 共用体
• 共用体类型的定义
–概述
共用体类型是由类型不同的、固定个数的成员所组成;所 有的共用体成员共占同一段内存,在微观上看,某一时刻 只能有某一个成员起作用,其它成员是不存在的。
– 定义形式:
union 共用体名 {类型名 成员名 ; 类型名1 类型名 成员名1; 类型名2 成员名2; 类型名 成员名 ; …… 类型名n 成员名n; 类型名 成员名 ; }; ; 首页 上一页
向函数传递结构体变量的地址是地址传递方式,被调函数中 可以通过实参传来的结构体变量的地址引用结构体变量,从而 在被调函数中对结构体变量的修改,也就间接的达到了改变主 调函数中的结构体变量的值的目的。 例9.3
• 向函数传递结构体数组
向函数传递结构体数组与传递其它的数组一样,实质上传递 的是数组的首地址,形参数组与实参数组共占内存单元。 例9.4
– 共用体类型的声明
typedef union {类型名 成员名1; 类型名 成员名2; …… 类型名 成员名n; }共用体类型名;
上一页
• 用户自定义类型的应用
– 应用:
• 对比较复杂且使用比较频繁的类型,可以用typedef声明 来简化程序的书写。 • 用typedef声明类型有助于提高程序的可移植性。
结构体数组stu的逻辑示意图为:
对于结构体类型的一维数组、二维数组,也可以定义指向 它们的指针变量,例如: struct student *ps=stu; 表示指针变量ps指向结构体数组stu的第0个元素,那么, ps+1表示stu[1]的地址,ps++表示指针向后移动一个元素的空 间,指向下一个元素。 上一页
首页 上一页
• 结构体变量的定义和初始化
– 结构体类型变量的定义方式:
• 用已经定义的结构体类型去定义结构体变量; • 定义结构体类型的同时定义结构体变量; • 定义无名结构体类型的同时定义结构体变量。
– 初始化:
可以在定义结构体变量的同时初始化。
– 说明:
• 定义结构体类型是说明一种由一些特定成员组成的模型。 模型并不是实体,变量才是占用内存的实体。 • 结构体变量的地址是结构体变量在内存的首地址,用来 存放结构体变量地址的变量是指向结构体的指针变量。 上一页
• 结构体变量的引用
–引用方式1: 结构体变量名.成员名 结构体变量名. –引用方式2: (*指针变量名).成员名 指针变量名)
或者是:指针变量名−>成员名 指针变量名−>成员名 指针变量名−> – 例:struct student {int number; char name[8]; int age; float score[3]; }stu={112, "wang",18,88,79,92},*ps=&stu; 那么对于变量stu的成员number的如下几种引用方式等效: ① stu.number;② (*ps).number;③ ps−>number;