C语言教程,结构体与共用体
学习目的:将不同的类型和对象组
织成一个组合项,称之为“记录”
和结构体 ;将不同类型的变量存放
到同一段内存单元中,可相互覆
盖,这种共同占用一段内存的结
构称为共用体。
结构体与共用体内容介绍
1 结构体类型声明、结构体类型变量定义和引用
2 结构体数组和指向结构体类型数据的指针
3 链表
4 共用体
5 枚举类型
6 用 typdef定义类型
什么是结构体数据类型?
一种构造数据类型
由不同数据类型成员构造而成
例如,学生构造体
struct stu
{
int num;
char name[20];
char sex;
float score;
};
定义一个结构的一般形式为,
struct 结构名
{成员表列 };
成员的定义形式为,类型说明符 成
员名 ;
分析如下定义,{ int num;
char name[20];
char sex;
float score; };
结构类型名为,struct stu,可以象
int,char,float一样用来定义变量的
类型 ;
结构名,stu,几乎不单独使用 ;
struct stu结构体类型在内存中的存
储结构
结构类型变量的说明说明结构变量有以下三种方法。
以上面定义的 stu为例来加以说明。
1,先定义结构,再说明结构变量。 如,
struct stu
{ int num;
char name[20];
char sex;
float score; };
struct stu boy1,boy2;
说明了两个变量 boy1和 boy2为 stu结构类型。也可以用
宏定义使一个符号常量来表示一个结构类型。例如,
#define STU struct stu
STU { int num;
char name[20];
char sex;
float score; } boy1,boy2;
2,在定义结构类型的同时说明结构变量。 例如,
struct stu{ int num;
char name[20];
char sex;
float score; }boy1,boy2;
这种形式的说明的一般形式为,
struct 结构名 {成员表列 }变量名表列 ;
3.直接说明结构变量。 例如,
struct {int num;
char name[20];
char sex;
float score;}boy1,boy2;
这种形式的说明的一般形式为,
struct {成员表列 }变量名表列 ;
成员也可以又是一个结构,即构成了嵌套的结构。
例如,
struct date
{ int month;
int day;
int year; };
struct{ int num;
char name[20];
char sex;
struct date birthday;
float score; }boy1,boy2;
结构变量成员的表示方法
允许具有相同类型的结构变量相互赋值
一般对结构变量的使用,包括赋值、输入、输出、运
算等都是通过结构变量的成员来实现的,不能将结构
体作为一个整体来处理。
表示结构变量成员的一般形式是, 结构变量名,成员名
例如,boy1.num 即第一个人的学号
boy2.sex 即第二个人的性别
如果成员本身又是一个结构则必须逐级找到最低级的
成员才能使用。
例如,boy1.birthday.month
成员可以当作一个变量来使用
结构变量的赋值,允许具有相同类型的结构变量
相互赋值 ;给各成员赋值 。
【 例 】 给结构变量赋值并输出其值。
main( )
{ struct stu{ int num;
char *name;
char sex;
float score; } boy1,boy2;
boy1.num=102; boy1.name="Zhang ping";
printf("input sex and score\n");
scanf("%c %f",&boy1.sex,&boy1.score);
boy2=boy1;
printf("Number=%d\nName=%s\n",boy2.num,boy2.name);
printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score); }
结构变量的初始化,和其他类型变量一样,对结
构变量可以在定义时进行初始化赋值。
【 例 】 对结构变量初始化。
main( )
{ struct stu /*定义结构 */
{ int num;
char *name;
char sex;
float score;
}boy2,boy1={102,"Zhang ping",'M',78.5};
boy2=boy1;
printf("Number=%d\nName=%s\n",boy2.num,boy2.name);
printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score); }
结构数组的定义,定义 方法和结构变量 定义
方法相似,只需说明它为数组类型即可。
struct stu { int num; char *name; char sex;
float score; }boy[5];
定义了一个结构数组 boy,共有 5个元素,boy[0]~ boy[4]。
对结构数组可以作 初始化 赋值。例如,
struct stu{ int num; char *name; char sex;
float score;
}boy[5]={{101,"Li ping","M",45},
{102,"Zhang ping","M",62.5},
{103,"He fang","F",92.5},
{104,"Cheng ling","F",87},
{105,"Wang ming","M",58}; }
当对全部元素作初始化赋值时,也可不给出数组长度。
【 例 】 计算学生的平均成绩和不及格的人数。
struct stu{ int num; char *name; char sex; float
score; }boy[5]={ {101,"Li ping",'M',45},
{102,"Zhang ping",'M',62.5},
{103,"He fang",'F',92.5},
{104,"Cheng ling",'F',87},
{105,"Wang ming",'M',58},};
main( )
{ int i,c=0; float ave,s=0;
for(i=0;i<5;i++)
{s+=boy[i].score;
if(boy[i].score<60) c+=1; }
printf("s=%f\n",s); ave=s/5;
printf("average=%f\ncount=%d\n",ave,c); }
指向结构变量的指针
结构指针变量定义的 一般形式 为,
struct 结构名 *结构指针变量名
例如,在前面的例题中定义了 stu这个结构,
如要说明一个指向 stu的指针变量 pstu,可写为:
struct stu *pstu;
赋值 是把结构变量的首地址赋予该指针变量,
不能把结构名赋予该指针变量。如果 boy是被
说明为 stu类型的结构变量,则,pstu=&boy
是正确的,而,pstu=&stu 是错误的。
结构指针变量 访问 结构变量的
各个成员,其访问的一般形式为:
(*结构指针变量 ).成员名
或为:结构指针变量 ->成员名
例如,(*pstu).num
或者,pstu->num
应该注意 (*pstu)两侧的括号不
可少,因为成员符,.”的优先
级高于,*”。如去掉括号写
作 *pstu.num则等效于
*(pstu.num),这样,意义就完
全不对了。
struct stu{ int num; char *name; char sex;
float score; } boy1={102,"Zhang ping",'M',78.5},*pstu;
main( )
{pstu=&boy1;
printf("Number=%d\nName=%s\n",boy1.num,boy1.name);
printf("Sex=%c\nScore=%f\n\n",boy1.sex,boy1.score);
printf("Number=%d\nName=%s\n",(*pstu).num,(*pstu).name
);
printf("Sex=%c\nScore=%f\n\n",(*pstu).sex,(*pstu).score);
printf("Number=%d\nName=%s\n",pstu->num,pstu->name);
printf("Sex=%c\nScore=%f\n\n",pstu->sex,pstu->score);}
指向结构数组的指针
设 ps为指向结构数组的指针变量,则 ps也指向该结构数组的 0号元素,
ps+1指向 1号元素,ps+i则指向 i号元素。这与普通数组的情况是一致的。
【 例 】 用指针变量输出结构数组。
struct stu
{
int num;
char *name;
char sex;
float score;
}boy[5]={
{101,"Zhou ping",'M',45},
{102,"Zhang ping",'M',62.5},
{103,"Liou fang",'F',92.5},
{104,"Cheng ling",'F',87},
{105,"Wang ming",'M',58},
};
main()
{
struct stu *ps;
printf("No\tName\t\t\tSex\tScore\t\n");
for(ps=boy;ps<boy+5;ps++)
printf("%d\t%s\t\t%c\t%f\t\n",ps->num,ps->name,ps->sex,ps->score);
}
注意:结构数组元素的地址和结构数组元素成员的地

结构指针变量可以指向一个结构变量或结构数组元素,可以
用来访问其成员
结构指针变量不能指向一个成员。也就是说不允许取一个成
员的地址来赋予它。因此,下面的赋值是错误的。
ps=&boy[1].sex;
而只能是,
ps=boy;(赋予数组首地址 )
或者是,
ps=&boy[0];(赋予 0号元素首地址 )
结构指针变量作函数参数
【 例 】 计算一组学生的平均成绩和不及格人数。
用结构指针变量作函数参数编程。
struct stu
{
int num;
char *name;
char sex;
float score;}boy[5]={
{101,"Li ping",'M',45},
{102,"Zhang ping",'M',62.5},
{103,"He fang",'F',92.5},
{104,"Cheng ling",'F',87},
{105,"Wang ming",'M',58},
};
main()
{
struct stu *ps;
void ave(struct stu *ps);
ps=boy;
ave(ps);
}
void ave(struct stu *ps)
{
int c=0,i;
float ave,s=0;
for(i=0;i<5;i++,ps++)
{
s+=ps->score;
if(ps->score<60) c+=1;
}
printf("s=%f\n",s);
ave=s/5;
printf("average=%f\ncount=%d\n",ave,c);
}
动态存储分配
回顾:C语言中不允许动态数组类型。
例如,
int n;
scanf("%d",&n);
int a[n];
提出问题,
实际所需的内存空间取决于实际输入的数据,而无法预先确定,如学生记录数组,学生人数不确定
解决问题,C语言中的内存管理函数,这些内存管理函数可以按需要动态地分配内存空间,也可把不再使用
的空间回收待用,为有效地利用内存资源提供了手段。
常用的三个内存管理函数,
分配内存空间函数 malloc
调用形式,
(类型说明符 *)malloc(size)
功能:在内存的动态存储区中分配一块长度为 "size"字节的连续区域。函数的返回值为该区域的首地址。
, size”是一个无符号数。
例如,
pc=(char *)malloc(100);(相当于,char a[100],*pc=a;)
pt=(struet stu*)malloc(sizeof(struct stu));
其中的 sizeof(struct stu)是求 stu的结构长度。
分配内存空间函数 calloc
calloc 也用于分配内存空间。
调用形式,
(类型说明符 *)calloc(n,size)
功能:在内存动态存储区中分配 n块长度为,size”字节
的连续区域。函数的返回值为该区域的首地址。
例如,
ps=(struet stu*)calloc(2,sizeof(struct stu));
释放内存空间函数 free
调用形式,
free(void*ptr);
功能:释放 ptr所指向的一块内存空间,ptr是一个任意
类型的指针变量,它指向被释放区域的首地址。被释
放区应是由 malloc或 calloc函数所分配的区域。
【 例 】 分配一块区域,输入一个学生数据。
main()
{
struct stu
{
int num;
char *name;
char sex;
float score;
} *ps;
ps=(struct stu*)malloc(sizeof(struct stu));
ps->num=102;
ps->name="Zhang ping";
ps->sex='M';
ps->score=62.5;
printf("Number=%d\nName=%s\n",ps->num,ps->name);
printf("Sex=%c\nScore=%f\n",ps->sex,ps->score);
free(ps);
}
共用体(联合体) 略
结束