第十章 结构体与共用体
1. 定义
结构体定义的一般形式:
struct 结构体名{
成员列表
};
定义一个结构体变量可以这样定义:struct 结构体名 结构体变量名;
2. 结构体变量的引用
在引用结构体变量时应注意以下规则:
1)不能将结构体变量作为一个整体输入输出,只能对变量当中的各个成员输入输出。新标准C允许将一个结构体变量直接赋值给另一个具有相同结构的结构体变量。
3. 结构体变量的初始化
如:
struct student
{long int num;
char name[20];
char sex;
char addr[20];
}a={89031,"Li Lin",'M',"123 Beijing Road" };
4. 结构体数组
struct student stu[4];
定义了一个数组stu,其元素为struct student类型,数组有4个元素。注意数组各元素在内存中是连续存放的。
在定义结构体数组时,数组元素个数可以不指定。编译时,系统会根据给出初值的结构体常量的个数来确定数组元素的个数。
5. 指向结构体变量的指针
因为结构体变量在内存中是连续存放各成员的,因此我们可以将结构体变量在内存中的起始地址存放到一个变量中,那么这个变量就是指向结构体变量的指针。
注意将结构体变量的首地址赋给指针变量的形式:
struct student stu_1;
struct student *p;
p=&stu_1; //要加取地址符 而指向函数和指向字符串的指针不用
在对引用结构体变量中的成员时,有三种方式:
以上面的结构体为例:设p为指向此结构体变量的指针,即p=&a;
1) a.num
2) (*p).num
3) p->num
6. 指向结构体数组的指针
struct student *p;
struct student stu[4];
p=stu;
则p为指向结构体数组的指针变量。这里应注意p++,p指向stu[0],p++则指向stu[1]。P指向的是数组中一个元素的首地址,而不能让p指向元素中的某一成员,如p=&stu.name是不对的。
7. 用指向结构体的指针作函数参数
虽然ANSI C允许用整个结构体作为函数参数,但要将全部成员值一个一个传递,开销大。所以用指针作参数,能提高运行效率。
Struct student stu;
用整个结构体作为参数调用形式:
fun( stu );
而且被调函数fun中也要定义成结构体变量,struct student stu;
用指针作参数调用形式:
fun( &stu );
被调函数fun中定义成指针变量,struct student *p;
8. 用指针处理链表
链表是一种重要的数据结构,原因就在于它可以动态的进行存储分配。链表都有一个头指针,用来存放整个链表的首地址。链表的定义形式如下:
struct node{
int num;
…
struct node *next;
};
next用来存放下一节点的地址。
如何进行动态的开辟和释放存储单元呢?c提供了以下有关函数:
1) malloc(size) 在内存的动态存储区开辟一个长度为size的连续空间。成功返回空间首地址,失败返回0;
2) calloc(n,size) 在内存的动态存储区开辟n个长度为size的连续空间。成功返回空间首地址,失败返回0;
3) free(ptr) 释放由ptr指向的内存区。Ptr是最近调用一次调用malloc和calloc时返回的值。
上面函数中,n和size为整型,ptr为字符指针。
9. 共用体
定义形式:
union 共用体名
{
成员列表
}变量列表;
共用体和结构体类似,只是有一点不同,结构体中个成员的起始地址不同,结构体变量在内存中的长度为各成员长度之和;而共用体中个成员的起始地址相同,共用体变量所占的内存长度为最长的成员的长度。
共用体类型数据的特点:
1) 同一个内存段可以存放几种不同类型的成员
2) 共用体变量中起作用的成员是最后一次存放的成员
3) 不能对共用体变量名赋值,不能在定义时初始化。
4) 不能把共用体变量作为函数参数
5) 共用体类型可以出现在结构体定义中,反之也可,也可以定义共用体数组。
另外,结构体名可以作为参数,而共用体名不可以。
这两中数据结构在不同场合中各有所用。
10. 枚举类型
定义形式如下:举个例子
enum weekday;
enum weekday workday,week_end; //定义枚举变量
workday和week_end被定义成枚举类型,他们的值只能为sun到sat之一。
也可以直接定义枚举变量,这一点与结构体相同
enum weekdaywordday,week_end;
注意:枚举元素是作为常量存在的,他们是有值的,c在编译时使他们的值按顺序为0,1,2…
如:上面的定义中,sun的值为0,mon的值为1
另外:虽然枚举元素有值,但不能将一个整数直接赋给一个枚举变量。应进行强制类型转换,如:
workday=(enum weekday)2;它相当于把tue赋给了workday。
11. 用typedef定义类型
typedef的作用就是能够让你定义一个自己喜欢的数据类型名来代替已有的数据类型名。如:
typedef int INT;那么我就可以用INT来定义整型变量了。作用和int一样。
Typedef用于结构体定义,如:
Typedef struct{
Int day;
Int month;
Int year;
}DATE;
DATE birthday;
DATE *p;等等
用typedef有利于程序的通用与移植。