第九章 结构体与共用体
§ 问题的提出,
同种类型的数据可以用数组来描述
如 20个学生的 C语言成绩可定义一个实型数组 cscore[20]
在解决实际问题过程中,还会遇到很多在描述同一个对象时,数据的类型不一致的情况。
例如表 4-1的学生成绩表。
第九章 结构体与共用体编号 姓名 基本工 资 奖金 提成 实发工 资
1 刘俊 500 100 400 1000
2 王军 500 100 200 800
3 丁建 500 100 500 1100
4 李文 500 200 700 1400
… … … … … …
struct worker
{
int num;
char name[20];
char sex;
int age;
char branch[20];
float pay;
float bonus;
float insurance;
float realpay;
}w;
[程序 ]
main()
{
printf(“\nPlease input worker?s
num,name,age,branch,pay,bonus,
insurance:\n”);
scanf(“%d%s%d%s%f%f%f”,&w.nu
m,w.name,&w.age,w.branch,&w.p
ay,&w.bonus,&w.insurance);
/*输入工人的各项信息 */
w.realpay=w.pay+w.bonus-w.insurance;
/*计算该工人的实发工资 */
printf(“%d\t%s\t%d\t%s\t%f\t%f\t%f\
t%f\n”,w.num,w.name,w.age,w.bran
ch,w.pay,w.bonus,w.insurance,w.real
pay);
/*打印该名工人的全部信息 */
}
第九章 结构体与共用体
§ 9.1 结构体
结构体是 一种 构造 数据类型 (教材 P14)
用途:把 不同类型 的数据组合成一个整体 -------
自定义 数据类型
结构体类型定义
struct [结构体名 ]
{
类型标识符 成员名;
类型标识符 成员名;
…………….
};
成员类型可以是基本型或构造型struct是 关键字,
不能省略合法标识符可省,无名结构体例 struct student
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
name
num
sex
age
score
addr
2字节
2字节
20字节
1字节
4字节
30字节

…..
结构体类型定义描述结构的组织形式,不分配内存例 struct student
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
struct student stu1,stu2;
§ 9.2 结构体变量的定义
先定义结构体类型,再定义结构体变量
一般形式,struct 结构体名
{
类型标识符 成员名;
类型标识符 成员名;
…………….
};
struct 结构体名 变量名表列 ;
例 #define STUDENT struct student
STUDENT
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
STUDENT stu1,stu2;
分开写
定义结构体类型的同时定义结构体变量一般形式,struct 结构体名
{
类型标识符 成员名;
类型标识符 成员名;
…………….
}变量名表列 ;
例 struct student
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu1,stu2;
分开写合写
直接定义结构体变量一般形式,struct
{
类型标识符 成员名;
类型标识符 成员名;
…………….
}变量名表列 ;
例 struct
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu1,stu2;
用 无名结构体 直接定义变量 只能一次分开写合写无名 (合写 )
说明
结构体类型与结构体变量概念不同
类型,不分配内存 ; 变量,分配内存
类型,不能赋值、存取、运算 ; 变量,可以
结构体可嵌套
结构体成员名与程序中变量名可相同,不会混淆
结构体类型及变量的作用域与生存期例 struct date{ int month;
int day;
int year;
};
struct student
{ int num;
char name[20];
struct date birthday;
}stu;
num name birthdaymonth day year
例 struct student
{ int num;
char name[20];
struct date
{ int month;
int day;
int year;
}birthday;
}stu;
num name birthdaymonth day year
§ 9.3 结构体变量的引用
引用规则
结构体变量 不能整体引用,只能引用变量 成员
可以将一个结 构体变量赋值给另一个结构体变量
结构体嵌套时 逐级引用成员 (分量 )运算符优先级,1
结合性,从左向右引用方式,结构体变量名,成员名例 struct student
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu1,stu2;
stu1.num=10;
stu1.score=85.5;
stu1.score+=stu2.score;
stu1.age++;
例 struct student
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu1,stu2;
printf(“%d,%s,%c,%d,%f,%s\n”,stu1); (?)
例 struct student
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu1,stu2;
stu2=stu1; ( )
例 struct student
{ int num;
char name[20];
struct date
{ int month;
int day;
int year;
}birthday;
}stu1,stu2;
num name birthdaymonth day year
stu1.birthday.month=12;
例 struct student
{ int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}stu1,stu2;
if(stu1==stu2)
…….,(?)
§ 9.4 结构体变量的初始化
形式一,struct 结构体名
{
类型标识符 成员名;
类型标识符 成员名;
…………….
};
struct 结构体名 结构体变量 ={初始数据 };
例 struct student
{ int num;
char name[20];
char sex;
int age;
char addr[30];
};
struct student stu1={112,“Wang Lin”,?M?,19,“200 Beijing Road”};
分开写
形式二:
struct 结构体名
{
类型标识符 成员名;
类型标识符 成员名;
…………….
}结构体变量 ={初始数据 };
例 struct student
{ int num;
char name[20];
char sex;
int age;
char addr[30];
}stu1={112,“Wang Lin”,?M?,19,“200 Beijing Road”};
分开写合写
形式三:
struct
{
类型标识符 成员名;
类型标识符 成员名;
…………….
}结构体变量 ={初始数据 };
例 struct
{ int num;
char name[20];
char sex;
int age;
char addr[30];
}stu1={112,“Wang Lin”,?M?,19,“200 Beijing Road”};
分开写合写无名 (合写 )
§ 9.5 结构体数组
结构体数组的定义三种形式:
形式一,
struct student
{ int num;
char name[20];
char sex;
int age;
};
struct student stu[2];
形式二,
struct student
{ int num;
char name[20];
char sex;
int age;
}stu[2];
形式三,
struct
{ int num;
char name[20];
char sex;
int age;
}stu[2];
num
name
sex
age
num
name
sex
age
stu[0]
stu[1]
25B
分开写合写无名 (合写 )
结构体数组初始化例 struct
{ int num;
char name[20];
char sex;
int age;
}stu[ ]={{……},{……},{……}};
顺序初始化,
struct student
{ int num;
char name[20];
char sex;
int age;
};
struct student stu[ ]={100,“Wang Lin”,?M?,20,
101,“Li Gang”,?M?,19,
110,“Liu Yan”,?F?,19};
例 struct student
{ int num;
name[20];
char s x;
int age;
}stu[ ]={{……},{……},{……}};
分行初始化,
struct student
{ int nu ;
char na e[20];
char sex;
int age;
};
struct student stu[ ]={{100,,ang Lin”,,20},
{101,“Li Gang”,,19},
{110,“Liu Yan”,?F?,19}};
全部初始化时维数可省
结构体数组引用引用方式,结构体数组名 [下标 ].成员名
stru t student
{ int num;
char name[20];
char sex;
int age;
}str[3];
stu[1].age++;
strcpy(stu[0].name,”ZhaoDa”);
例 统计候选人选票
struct person
{ char name[20];
int count;
}leader[3]={“li”,0,“Zhang”,0,”Wang“,0};
main()
{ int i,j; char leader_name[20];
for(i=1;i<=10;i++)
{ scanf("%s",leader_name);
for(j=0;j<3;j++)
if(strcmp(leader_name,leader[j].name)==0)
leader[j].count++;
}
for(i=0;i<3;i++)
printf("%5s:%d\n",leader[i].name,leader[i].count);
}
name count
Li
Zhang
Wang
0
0
0
§ 9.6 结构体和指针
指向结构体变量的指针
定义形式,struct 结构体名 *结构体指针名 ;
例 struct student *p;
使用结构体指针变量引用成员形式 存放结构体变量在内存的起始地址
num
name
sex
age
stu
pstruct student{ int num;
char name[20];
char sex;
int age;
}stu;
struct student *p=&stu;
(*结构体指针名 ).成员名 结构体指针名 ->成员名 结构体变量名,成员名指向运算符优先级,1
结合方向:从左向右例 指向结构体的指针变量
main()
{ struct student
{ long int num;
char name[20];
char sex;
float score;
}stu_1,*p;
p=&stu_1;
stu_1.num=89101;
strcpy(stu_1.name,"Li Lin");
p->sex='M';
p->score=89.5;
printf("\nNo:%ld\nname:%s\nsex:%c\nscore:%f\n",
(*p).num,p->name,stu_1.sex,p->score);
}
例 int n;
int *p=&n;
*p=10;? n=10
struct student stu1;
struct student *p=&stu1;
stu1.num=101;? (*p).num=101
指向结构体数组的指针例 指向结构体数组的指针
struct student
{ int num;
char name[20];
char sex;
int age;
}stu[3]={{10101,"Li Lin",'M',18},
{10102,"Zhang Fun",'M',19},
{10104,"Wang Min",'F',20}};
main()
{ struct student *p;
for(p=stu;p<stu+3;p++)
printf("%d%s%c%d\n",p->num,p->name,p->sex,p->age);
}
num
name
sex
age
stu[0]
p
stu[1]
stu[2]
p+1
用指向结构体的指针作函数参数
用结构体变量的成员作参数 ----值传递
用指向结构体变量或数组的指针作参数 ----地址传递
用结构体变量作参数 ----多值传递,效率低
§ 9.8 共用体
构造数据类型,也叫联合体
用途:使几个不同类型的变量共占一段内存 (相互覆盖 )
共用体类型定义定义形式:
union 共用体名
{
类型标识符 成员名;
类型标识符 成员名;
…………….
};例 union data
{ int i;
char ch;
float f;
}; f
ch
i 类型定义 不分配内存形式一,
union data
{ int i;
char ch;
float f;
}a,b;
形式二,
union data
{ int i;
char ch;
float f;
};
union data a,b,c,*p,d[3];
形式三,
union
{ int i;
char ch;
float f;
}a,b,c;
共用体变量的定义
f
ch
i
f
ch
i
a b
共用体 变量定义 分配内存,
长度 =最长成员 所占字节数共用体 变量任何时刻只有 一个成员 存在三种定义形式,
分开写合写无名 (合写 )
共用体变量引用
引用方式:
例 a.i=1;
a.ch=?a?;
a.f=1.5;
printf(“%d”,a.i); (?编译通过,运行结果不对 )
引用规则
不能引用共用体变量,只能 引用其成员共用体指针名 ->成员名共用体变量名,成员名 (*共用体指针名 ).成员名
union data
{ int i;
char ch;
float f;
};
union data a,b,c,*p,d[3];
a.i a.ch a.f
p->i p->ch p->f
(*p).i (*p).ch (*p).f
d[0].i d[0].ch d[0].f
共用体变量中起作用的成员是 最后一次存放的成员例 union
{ int i;
char ch;
float f;
}a;
a=1; (?)
不能 在定义共用体变量时 初始化例 union
{ int i;
char ch;
float f;
}a={1,?a?,1.5}; (?)
可以用一个共用体变量为另一个变量赋值例 float x;
union
{ int i; char ch; float f;
}a,b;
a.i=1; a.ch=?a?; a.f=1.5;
b=a; (?)
x=a.f; (?)
例 将一个整数按字节输出
01100001 01000001
低字节高字节
01000001
01100001
ch[0]
ch[1]
运行结果:
i=60501
ch0=101,ch1=141
ch0=A,ch1=a
main()
{ union int_char
{ int i;
char ch[2];
}x;
x.i=24897;
printf("i=%o\n",x.i);
printf("ch0=%o,ch1=%o\n
ch0=%c,ch1=%c\n",
x.ch[0],x.ch[1],x.ch[0],x.ch[1]);
}
结构体与共用体
区别,存储方式不同
struct node
{ char ch[2];
int k;
}a;
union node
{ char ch[2];
int k;
}b;
achk
bch k
变量的各成员同时存在任一时刻只有一个成员存在
联系,两者可相互嵌套
9,9 枚举类型所谓,枚举,,是指将变量的所有取值一一列举出来,变量的取值只限于列举出来的值的范围。该变量称之为枚举型变量。
所列举的值叫做 枚举元素 (枚举常量)。
定义一个枚举类型名,再用它定义变量。
enum 枚举类型名
{枚举元素1,枚举元素2,...,枚举元素 n};
enum 枚举类型名 变量列表;
关键字 类型名和枚举元素名由用户自己命名类型名和枚举元素名由用户自己命名例 1:
enum weekday{ sun,mon,tue,wd,thu,fri,dat };
enum weekday day;
例 2:
enum weekday {sun,mon,tue,wd,thu,fri,dat } day;
例 3:
enum {sun,mon,tue,wd,thu,fri,dat } day;
说明:
1,C语言中枚举元素按 常量 处理,它们是有值的。它们的值是系统按其定义顺序自动赋予的 0,1,2,3,4,…… 。
因此上例中的枚举元素 sun的值为 0,mon的值为 1,依次类推。枚举变量的值即是它所取的枚举元素的值,此值可输出查看,如 day= fri;则 day的值为 5,可以输出 printf(“%d”,day);
输出结果为 5。
2、枚举元素的值也可以改变,但必须在定义时指定。
如,enum weekday {sun=7,mon=1,tue,wd,thu,fri,dat };
如果定义时未指定值,则按顺序取默认值。
3、枚举元素是常量,不是变量,不能在定义以外的任何位置对它们赋值,如 sun=5;
4、枚举值可用来做判断比较,如:
if(day==sun) …… ;
if(day>mon &&day<fri) ……
5、枚举变量取值只能是所列举的枚举元素,不能直接赋予一个整数值,如,day= 2;
当然可以采用强制类型转换的方式赋值,
但多数情况不采用。
§ 9.9 用 typedef定义类型
功能,用自定义名字为 已有 数据类型命名
类型定义 简单形式,typedef type name;
例 typedef int INTEGER;类型定义语句关键字 已有数据类型名 用户定义的类型名例 typedef float REAL;
类型定义后,与已有类型一样使用例 INTEGER a,b,c;
REAL f1,f2;
int a,b,c;
float f1,f2; 说明,1.typedef 没有创造 新数据类型
2.typedef 是定义类型,不能定义变量
3.typedef 与 define 不同
define typedef
预编译时处理 编译时处理简单字符置换 为已有类型命名