大学实用教程 C语言
第8章 结构体与共用体 问题的提出 结构体类型与结构体变量 结构体数组 结构体与函数 共用体
§8.1 问题的提出 如果只存储某班的某门课程的成绩,可使用一维数 组;只存储若干门课程的成绩,可用二维数组;对于 下表该如何组织数据,采用什么存储结构? 学号 姓名 性别 入学时间 计算机原理 C语言 编译原理 操作系统 1 令狐冲 男 2006 90 83 72 82 2 林平之 78 92 88 3 岳灵珊 女 89 98 66 4 任莹莹 95 87 5 …… 6
采用分散的一维数组结构 int studentId[30] = {1,2,3,4,5,6}; char studentName[10][30] = {{"令狐冲"},{"林平之"}, {"岳灵珊"},{"任莹莹"}}; char studentSex[2][30] = {{"男"},{"男"},{"女"},{"女"}}; int timeOfEnter[30] = {2006,2006,2006,2006}; int scoreComputer[30] = {90,78,89,78}; int scoreEnglish[30] = {83,92,72,95}; int scoreMath[30] = {72,88,98,87}; int scoreMusic[30] = {82,78,66,90};
数据的内存管理方式 90 78 89 …… 83 92 72 95 88 98 87 82 66 1 2 3 4 令狐冲 林平之 岳灵珊 任莹莹 男 女 2006 2000 4000 4E00 F010 10F0 EE00 CE00 6600
存储学生信息的设想 建立一个长度为30的数组,其中的每一个数组元素就是一个学生的学生考试信息,每一个数组元素的理想存储结构可为: StudentName TimeOfEnter Score_2 Score_4 StudentId StudentSesx Score_1 Score_3 学号 姓 名 性别 入学 原理 C 编译 OS 一个完整的变量
§8.2 结构体类型与结构体变量 格式 结构体名 成员、域 其中:标识符是定义的结构体类型名; 一、结构体的声明 struct 标识符 { 类型1 域名1; 类型2 域名2; …… 类型n 域名n; }; 格式 结构体名 成员、域 其中:标识符是定义的结构体类型名;
举例 定义学生档案的结构体 struct personnel { int num; char name[10]; char sex; int age; float score; char addr[30]; };
struct personnel person; 二、定义结构体的变量 变量说明 struct 类型 变量名,……; struct personnel person;
struct personnel stu1, stu2; 1、先声明类型后定义变量 struct personnel { int num; char name[10]; char sex; int age; float score; char addr[30]; }; struct personnel stu1, stu2;
等价 2、在声明同时定义变量 struct personnel { int num; char name[10]; char sex; int age; float score; char addr[30]; }student1, student2; struct personnel { int num; char name[10]; char sex; int age; float score; char addr[30]; }; struct personnel student1, student2; 等价
struct { int num; char name[10]; char sex; int age; float score; 3、直接定义结构类型变量 struct { int num; char name[10]; char sex; int age; float score; char addr[30]; }student1, student2;
4、成员也可以是一个结构体变量 如:struct date { int month; int day; int year; }; struct student { int num; char name[10]; struct date birthday; }stu1; num name birthday month day year
格式 struct 结构类型名 *指针名; 举例 struct student *p, stu1; p=&stu1; 5、定义指向结构体的指针变量 格式 struct 结构类型名 *指针名; 举例 struct student *p, stu1; p=&stu1; 指针p即指向结构体变量stu1的首地址。
格式 结构体变量名.域名 举例 输出学生档案数据 三、结构体变量的引用 1、圆点运算符 printf("%d",person.num); printf("%s",person.name); printf("%c",person.sex); printf("%d",person.age); printf("%f",person.score); printf("%s",person.addr);
struct personnel *p, stu1; p=&stu1; 2、箭头运算符 域表示 结构指针名->域名 举例 struct personnel *p, stu1; p=&stu1; p -> num 等价于 (*p).num
结构体变量引用说明 ⒈不能将一个结构体变量作为一个整体 进行输入和输出。下面是错误的: printf("%d,%s,%c,%d,%f,%s\n", student1); 而应按成员输入和输出。 printf(“%d\n”,student1.num); printf(“%s\n”,student1.name);
⒉如果成员本身又属一个结构体类型, 则要用若干个成员运算符,一级一级地 找到最低一级的成员。只能对最低一级 的成员进行赋值、存取和运算。 struct date struct student {int month; {int num; int day; char name[10] int year; struct date birthday; }; }student1,student2; 例如:student1.num student1.birthday.month
⒊对结构体变量的成员可以像普通变量一样进行各种运算。 ⒋可以引用结构体变量成员的地址,也可以引用结构体变量的地址。 例如: scanf("%x", &student1.num); printf("%x", &student1);
思考题 struct point { int x; int y; }; struct rect { struct point pt1; struct point pt2; }; struct rect rt, *rp=&rt; 下面表达式哪些合法? rt.pt1.x (*rp).pt1.x rp->pt1.x rt->pt1.x 上面合法的表达式都是等价的吗?
5、结构体变量的初始化 struct personnel { long int num; char name[10]; char sex; int age; char addr[30]; }stu={89031, " li san ", 'm', 18, " 123 beijing road "};
§8.3 结构体数组 struct personnel { int num; char name[10]; char sex; 1、声明结构体 struct personnel { int num; char name[10]; char sex; int age; float score; char addr[30]; };
格式 2、定义结构体数组 struct personnel { int num; char name[10]; char sex; int age; float score; char addr[30]; }; struct personnel stu[3];
struct personnel stu[3] ={ 3、初始化结构体数组 struct personnel stu[3] ={ {10101,"Li lin",'m',18,87.5,"103 Beijing road"} {10102,"Zhang li",'f',19,99,"130 Shanghai road"} {10103,"Wang bin",'m',20,78.5,"26 zhongshan road"} }; num name sex age score addr 10101 Li lin m 18 87.5 103 beijing road 10102 Zhang li f 19 99 130 shanghai road 10104 Wang bin 20 78.5 26 zhongshan road stu[0] stu[1] stu[2]
struct personnel stu[30], *p; p=stu; *p ⇔ stu[0] *(p+1) ⇔ stu[1] 4、结构体数组和指针 struct personnel stu[30], *p; p=stu; *p ⇔ stu[0] *(p+1) ⇔ stu[1] *(p+2) ⇔ stu[2] *(p+3) ⇔ stu[3] stu[1].num ⇔ (*(p+1)).num ⇔ (p+1)->num
5、结构体类型应用举例: (1)已知:struct sk { int a; float b; }data, *p; 若有 p = &data; 则正确的引用data 中成员a 的方是: (*p).data.a B. (*p).a C. p->data.a D. p.data.a B
printf(“%d,%d\n”,++p->x,(++p)->x); } (2)读程序,写出运行结果。 main() { struct { int x; int y; }s[2]={{1,2},{3,4}},*p=s; printf(“%d,%d\n”,++p->x,(++p)->x); } 4,3
§8.4 结构体与函数 把结构体传递给函数的方式有三种: 1.用结构体的单个成员作参数 在一般情况下,用单个成员作为实参给函数传递参数与普通的值传递没有分别,可看成普通的实参,是单向值传递,在函数内部对参数进行操作不影响结构体的变化。
main() { struct number { int num1; int num2; }num; num.num1=5; num.num2=4; f(num.num1, num.num2); . } void f(int m,int n) { for(i=1;i<=m;i++) for(j=1;j<=n;j++) printf(“*”); }
要求 举例 2、用结构体整体作为实参 实参和形参的数据类型相同(单向值传递) struct date { int year; int month; int day; }; void func(struct date p) p.year = 2000; p.month = 5; p.day = 22; } main() struct date d; d.year = 1999; d.month = 4; d.day = 23; printf(“%d,%d,%d\n”,d.year, d.month, d.day); func(d); 举例
要求 实参和形参指向相同的数据类型。 举例 3、用指向结构体的指针作为实参 struct date { int year; int month; int day; }; void func(struct date *p) (*p).year = 2000; (*p).month = 5; (*p).day = 22; } main() struct date date1,*d=&date1; d->year = 1999; d->month = 4; d->day = 23; printf("%d,%d,%d\n",(*d).year, (*d).month, (*d).day); func(d); printf("%d,%d,%d\n",d->year, d->month, d->day); 举例
给已定义的数据类型定义别名。 功 能 举 例 typedef int integer; typedef struct student stu; 说明 struct student stu1, stu2; 等价于 stu stu1,stu2; 使用别名时,可不使用struct。
§8.5 共用体—联合体 什么是共用体? 是C语言提供的一种存储共享的设施。 即将若干个名称不同、类型不同的数据共 享同一存储单元。也就是使用覆盖技术, 几个长度不同的变量相互覆盖。
格式 变量序列是 可选项。 举例 说明 一、共用体类型的定义 union data{ int i; char ch; float f; }; 类型1 成员1; 类型2 成员2; …… 类型n 成员n; }[变量序列]; 变量序列是 可选项。 union data{ int i; char ch; float f; }; union data{ int i; char ch; float f; } a; 举例 说明 共用体所占存储单元长度是成员的最大者。
⒉结构体所占存储空间的大小是所有 成员所占空间大小的总和。 共用体所占存储单元的大小是所有 成员中占用空间最大的。 二、共用体与结构体的区别 ⒉结构体所占存储空间的大小是所有 成员所占空间大小的总和。 共用体所占存储单元的大小是所有 成员中占用空间最大的。 ⒈结构体的每一个成员都占用自己的 存储空间。 共用体的每个成员共享同一个存储 单元。
格式 变量名. 成员名 举例 说明 不能只引用共用体变量,例如: printf("%d", a); × 而应是: 三、共用体类型数据的访问 格式 变量名. 成员名 a.i 引用共用体变量a中的整形变量i a.ch 引用共用体变量a中的字符变量ch a.f 引用共用体变量a中的实型变量f 举例 说明 不能只引用共用体变量,例如: printf("%d", a); × 而应是: printf("%d", a.i); √ printf("%c", a.ch); √ printf("%f", a.f); √
四、共用体类型数据的特点 1.不能把共用体变量作为函数参数,也不能使函数带回共用体变量,但可以使用指向共用体变量的指针。 2.共用体变量可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型定义中,数组也可以作为共用体的成员。 3.共用体变量不能进行比较操作。
a.b.c1= a.b.c2= 五、共用体程序举例 0x34 0x12 #include <stdio.h> main() { union { int x; struct { char c1; char c2; } b; }a; a.x=0x1234; printf("a.b.c1=%#x\ta.b.c2=%#x\n",a.b.c1,a.b.c2); } 0x34 0x12