第九章 用户自己建立的数据类型
- 9.1 定义和使用结构体变量
- 9.1.1 自己建立结构体类型
- 1.C语言允许用户自己建立由不同数据类型组成的组合型数据结构,称为结构体。
- 2.**声明结构体类型**的形式:struct 结构体名 {成员表列};说明:①结构体类型名= struct (关键字)+结构体名;②结构体成员(域)命名:类型名 成员名。③结构体成员可以属于另一结构体类型,例:struct Student {int num; struct Date birthday; } ; struct Date { int month; int year } //struct Student中的 Date成员属于Date结构体类型。
- 9.1.2 定义结构体变量
- (1)先声明类型,再定义该类型的变量;例 :struct Student { 成员表列};struct Student s1 ,s2;
- (2)声明类型和定义变量同时进行;struct Student(类型名) { 成员表列} st1 , st2(变量表列);
- (3)不指定内类型名直接定义结构体变量(很少使用);struct { 成员表列} 变量表列。
- 注意:结构体类型和结构体变量是不同的概念;结构体中的成员名可以和程序中的变量同名,但是二者表示不同的对象;结构体中的成员的作用与地位相当于普通变量。
- 9.1.3 结构体变量的初始化和引用
- (1)在定义结构体变量时可以对其成员进行初始化;也可以只对已经定义的变量的某一个成员初始化,例:struct Student a ={.name=”Tom”};//其他未被初始化的数值型成员被系统初始化为0,字符型初始化为\0,指针型初始化为NULL。
- (2)引用结构体变量成员的值:结构体变量名. 成员名。说明:**“.”**是成员运算符,其在所有运算符中优先级最高;不能一次输出所有成员的值。
- (3)如果成员又属于另一个结构体类型,则需要用若干个成员运算符找到最低一级的成员,student. birthday. year;
- (4)结构体变量的成员可以进行像普通变量的各种运算(根据其类型)。student.age++;
- (5)同类型的结构体变量可以相互赋值。student1=student2 ;//s1,s2为相同类型的变量。
- (6)可以引用结构体成员和结构体变量的地址。&s1 ,& s1. name;
- 9.1.1 自己建立结构体类型
- 9.2 使用结构体数组
- 9.2.1 定义结构体数组
- (1)定义:① struct 结构体名 {成员表列} 数组名 [数组长度]。② 先声明一个结构体类型,再用此类型定义一个结构体数组,结构体类型 数组名 [数组长度];struct Student s1[2]={1,”Lihua”}。
- (2)初始化:在已定义数组的后面加上 ={初值表列}。
- 9.2.1 定义结构体数组
- 9.3 结构体指针
- 即是指向结构体变量的指针,一个变量的起始地址就是结构体变量的指针。
- 9.3.1 指向结构体变量的指针
- (1)结构体指针既可以指向结构体变量也可以指向结构体数组中的元素,但是指针变量的基类型必须与结构体变量的类型一致 struct Person *p1 , p2; p1=p2 ;//p1 的基类型为 struct Person 而p2 的类型也是它。
- (2) struct Person{ int num ; char name} ;struct Person p1 , p2 ; p1=p2 ;printf(“%d”,(p).num) //(*p).num:表示p指向结构体变量中的成员num(引用结构体变量的成员),等于p->num;
- 9.3.2 指向结构体数组(元素)的指针
- struct Person { int num,char name} stu[]={1,”tom”};struct Person *p1 ;p1=stu;//p1=stu 表示p1指向数组第一个元素stu[0];
- 注意:p指向的是数组某一元素,不应用来指向数组元素的某一成员,此时会出现”类型不匹配”的警告。
- 9.3.3 用结构体变量和结构体变量的指针作函数参数
- (1)把一个结构体变量的值传递给另一函数的3方法:① 用结构体变量的成员作实参,属于“值传递”与通变量一样的用法;② 用结构体变量作实参 ,也是“值传递”方式(较少使用);③ 指向结构体变量(或数组元素)的指针作实参。
- *9.4 用指针处理链表
- 9.4.1 链表的含义
- 1.链表有一个头指针变量(head),存放一个地址,该地址指向一个元素(结点);每个结点包括:①用户需要用的实际数据,② 下一节点的地址。
- 2.链表中各元素在内存中的地址可以是不连续的。注意: 要找到某一元素,必须先找到上一个元素,根据其存储的下一元素的地址才能找到下一元素;链表无头指针则整个链表都无法访问;链表中间不能断开。
- 3.一个指针类型结构体成员既可以指针其他类型的结构体数据,也可以指向自己所在的结构体类型。
- 9.4.2 静态链表和动态链表
- 1.静态链表:所有系结点都是在程序中定义的,不是临时开辟的,也不能用用完后释放。
- 2.动态链表
- 一个一个的开辟节点和输入各结点的数据,并建立前后相链的关系。
- 注:函数 sizeof( ) 意义是求字节数的运算,当操作数为字符串时,结果包括空字符“\0”;而strlen() 是求实际长度,不包括“\0”.
- 9.4.3 输出链表
- 例9-10(见P315), struct Student {long num;float score;struct Student next }; struct Student *p; p=p->next//p->next,是p所指向的结点中的next成员,这里next成员存放了第二个结点的地址,执行p=p->next后p就指向第二个结点。
- 9.4.1 链表的含义
- 9.5 共用体类型
- 9.5.1 共用体类型的介绍与定义
- 1.用同一段内存单元存放不同类型的变量;使几个不同的变量共享一段内存的结构,称为“共用体”类型的结构。
- 定义共用体类型变量:① 一般形式:union 共用体名{ 成员表列 }变量表列;② 声明类型同时定义变量:union Date { long year ; int month; int day } a,b,c; ② 类型声明与变量定义分开:union Date { long year ; int month; int day } ; union Date a,b,c; ③ d定义时省略共用体名。
- 3 . 共用体和结构体的比较
- 共用体和结构体的定义形式相似,但是含义不同。
- 构体变量所占的内存长度是各个成员所占内存长度之和,每个成员有其单独的的内存单元。共用体变量所占内存长度是内存最长的成员的内存长度。
- 9.5.2 引用共用体变量
- 注意:只有定义后才能引用;不能引用变量,只能引用其成员。
- 方式:共用体变量名. 成员名
- 9.5.3 共同体类型数据的特点
- 同一个内存段可以用来存放几种不同类型的成员,但在每一瞬间只能存放其中的一个成员。也就是说某个共用体变量只能存放一个值。
- 可以对共用体变量初始化,但初始化表中只能有一个常量,一次只能初始化一个成员。union Data a={16} , //对第一个成员初始化;union Data a={.ch=’j’} ; // 指定成员的初始化
- 对共用体变量成员的赋值中,后面成员的赋值会取代前面成员的赋值或原有存储单元中的值。
- 4.共用体变量的地址和它各成员的地址都为同一地址
- 5.不能对共用体变量赋值,同类型的变量可以相互赋值。
- 6.(1)共用体类型可以出现在结构体类型的定义中,结构体也可以出现在共用体类型的定义中;(2)可以定义共用体数组,数组也可以作为共用体成员。
- 说明:class :为C语言的关键字;%-6d :表示 以十进制整数形式输出,占6列,向左对齐。
- 9.5.1 共用体类型的介绍与定义
- 9.6 枚举类型
- 1.含义:“枚举”:就是把可能的值一一列举出来(适用于一个变量只有几种可能的值),变量的值只限于列举出来的值。
- 2.定义枚举类型
- (1)声明:enum 枚举名 [枚举元素(枚举常量)列表];enum Person { zhangsan ,lisi ,xiaoming,tom };
- (2)定义:enum 枚举名 变量表列 ;enum Person person1,person2 ;
- (3)定义和声明可以组合在一起;可以不声明有名字的枚举类型,而直接定义枚举变量。
- 3.说明
- (1)枚举元素相当于常量,不能对其赋值。
- (2)每一个元素代表一个整数,C语言编译会按定义时的顺序默认元素的值为 0, 1 , 2, 3····; 可以引用和输出常量。
- (3)在定义枚举类型时可以显式的指定枚举元素的值。
- (4)枚举元素的比较时是按初始化时指定的值或默认的数值来作比较的。
- 9.7 用typedef声明新类型名
- 1.简单地使用typedef
- 格式:typedef + 按定义变量的方式,把变量名换为新类型名。标准类型名/自定义类型(定义体) ;typedef int Integer;typedef int Num[2]; 标准类型:(int char float daouble等),自定义类型:结构体、共用体、枚举类型。
- 说明 :① 习惯上把typedef声明的类型名第一个字母用大写表示;② 注意用typedef只是对已经存在的类型指定一个新的名字而没有创造新的类型。③ typedef 与 # define的联系与区别: typedef int Integer ; Intger a,b,c; # define Integer int 作用都是用Integer 代替int ;但是# define 是在预编译阶段处理的,它只能作简单的字符替换。而 typedef 是在编译阶段处理,它实际上是先定义一个新的类型名,在用此类型名来定义变量。
- 用一个简单类型 名代替复杂类型
- 例:typedef struct { int num; char name} Person; //Person代表一个结构体类型。
- typedef char String; //定义String为字符指针类型,typedef int ( Pointer)( );//定义Pointer为指向函数的指针,返回整型值。
- 1.简单地使用typedef
