1、第 10 章 共用体与枚举类型,10.1 共用体类型与共用体变量,返回,C语言程序设计教程,10.2 共用体变量的引用,10.3 共用体变量的应用,10.4 位运算与位段结构,10.5 枚举类型,10.6 类型定义,10.1 共用体类型与 共用体变量,共用体是C的由用户定义的数据类型。共用体把不同类型的数据项组成一个整体,这些不同类型的数据项在内存中所占用的起始单元是相同的。,1. 共用体类型的定义 共用体类型定义用关键字union标识, 形式为:,下一页,第10章 共用体与枚举类型,上一页,union 标识符 成员说明列表 ;,标识符给出共用体名, 是共用体类型名的主体, 定义的共用体类型由
2、“union 标识符”标识。例如,定义一个共用体类型, 要求包含一个整型成员,一个字符型成员和一个单精度型成员: union icf int i; char c; float f; ;,下一页,第10章 共用体与枚举类型,上一页,2 共用体变量的定义,(1) 先定义共用体类型, 再定义共用体变量: union 共用体名成员表; union 共用体名 变量表; ,例如:union data int i;char ch;float f;union data a,b,c;,下一页,第10章 共用体与枚举类型,上一页,(2) 定义共用体类型的同时定义共用体变量,例如: union data int i
3、;char ch;float f;a,b,c; ,下一页,第10章 共用体与枚举类型,上一页,union 共用体名 成员表 变量表;,(3)定义共用体类型时,省略共用体类型名,同时定义共用体类型变量,union 成员表 变量表;,第10章 共用体与枚举类型,例如: union int i;char ch;float f; a,b,c; ,返回,10.2 共用体变量的引用,共用体变量不能直接使用,只能使用里面的某个成员,其成员同样通过点运算描述。形式为: 共用体变量名.成员名例如,定义上面共用体类型变量a ,a占有4个字节的空间,a.i 表示其整型成员,a.ch表示其字符型成员,a.f表示其单精
4、度型成员。,下一页,第10章 共用体与枚举类型,上一页,(1) 共用体变量中,可以包含若干个成员及若干种类型,但共用体成员不能同时使用。在每一时刻,只有一个成员及一种类型起作用,不能同时引用多个成员及多种类型。,下一页,第10章 共用体与枚举类型,上一页,说明,(2) 共用体变量中起作用的成员值是最后一次存放的成员值,即共用体变量所有成员共用同一段内存单元,后来存放的值将原先存放的值覆盖,故只能使用最后一次给定的成员值。如: a.i=278, a.ch=D, a.f=5.78; 不能企图通过下面的printf函数得到a.i和a.ch的值:printf(“%d,%c,%f”, a.i, a.ch
5、, a.f); 但能得到a.f的值。,(3) 共用体变量的地址和它的各个成员的地址相同。 (4) 不能企图引用共用体变量名来得到某成员的值。 (5) 共用体变量不能作函数参数,函数的返回值也不能是共用体类型。 (6) 共用体类型和结构体类型可以相互嵌套,共用体中成员可以为数组,甚至还可以定义共用体数组。,下一页,第10章 共用体与枚举类型,上一页,写出下列程序的执行结果,main() union exxint a,b;struct int c,d;lpp; e=10; e.b=e.a+20; e.lpp.c=e.a+e.b; e.lpp.d=e.a*e.b; printf(“%d,%dn”,e
6、.lpp.c,e.lpp.d); ,第10章 共用体与枚举类型,例10.1,运行结果:60,3600,返回,设有若干教师的数据,包含有教师编号、姓名、职称,若职称为讲师,则描述他们的所讲课程,若职称为教授,则描述他们所写论文数目。,下一页,第10章 共用体与枚举类型,上一页,10.3 共用体变量的应用,例10.2,点击,查看程序请,10.4 位运算与位段结构,位是指二进制数的一位,其值为0或1。位段以位为单位定义结构体(或共用体)中成员所占存储空间的长度。含有位段的结构体类型称为位段结构。,下一页,第10章 共用体与枚举类型,上一页,10.4.1 位运算在用位运算符进行数的运算时,数是以补码的
7、形式参加运算的。,1. 位运算(主要有:&、|、),(1)&(按位“与”) 运算规则为:0&0=0,0&1=0,1&0=0,1&1=1 例如,-5&3的值为3。其中-5的补码(为简便起见,用8位二进制表示)为1111 1011,3的补码为0000 0011,按位与的结果为0000 0011,即值为十进制数3。,下一页,第10章 共用体与枚举类型,上一页,(2)|(按位“或”),运算规则为:0|0=0,0|1=1,1|0=1,1|1=1 例如,-5|3的值为-5。-5与3相位或后得11111011,其真值为-0000101,即-5。,(3)(按位“异或”) 运算规则为:00=0,01=1,10=
8、1,11=0 例如,-53的值为-8。 (4)(按位“取反”) 运算规则为:0=1,1=0 例如,7的值为-8。 (5)(“左移”) 例如,32,将3左移2位,右边(最低位)补0, 结果为12,相当于322的结果。,下一页,第10章 共用体与枚举类型,上一页,(6)(“右移”) 移动对象为正数时,高位补0。为负数时,逻辑右移,高位补0;算术右移,高位补1。Turbo C采用的是算术右移,有的C语言版本则采用逻辑右移。 例如,-32,将3右移2位,左边(最高位)补1,结果为-1。,下一页,第10章 共用体与枚举类型,上一页,10.4.2 位段结构,位段结构也是一种结构体类型,只不过其中含有以位为
9、单位定义存储长度的整数类型位段成员。采用位段结构既节省存储空间,又可方便操作。,位段结构中位段的定义格式为:unsigned : 例如: struct bytedata unsigned a:2; /*位段a,占2位*/unsigned:6; /*无名位段,占6位,但不能访问*/unsigned:0; /*无名位段,占0位,表下一位段从下一字边界开始*/unsigned b:10; /*位段b,占10位*/int i; /*成员i,从下一字边界开始*/ data;,下一页,第10章 共用体与枚举类型,上一页,(1)一个位段必须存储在同一存储单元(即字)之中,不能跨两个单元。如果其单元空间不够,
10、则剩余空间不用,从下一个单元起存放该位段。 (2)可以通过定义长度为0的位段的方式使下一位段从下一存储单元开始。,下一页,第10章 共用体与枚举类型,上一页,位段数据的引用,同结构体成员中的数据引用一样,但应注意位段的最大取值范围不要超出二进制位数定的范围,否则超出部分会丢弃。 例如:data.a=2; 但 data.a=10;就超出范围(a占2位,最大3),关于位段数据,注意以下几点,(3)可以定义无名位段。 (4)位段的长度不能大于存储单元的长度。 (5)位段无地址,不能对位段进行取地址运算。 (6)位段可以以%d,%o,%x格式输出。 (7)位段若出现在表达式中,将被系统自动转换成整数。
11、,下一页,第10章 共用体与枚举类型,上一页,编程将一个16进制整数(占2字节)的各位循环左移4个二进制位,如2fe1循环左移4个二进制位后为fe12。,具体步骤为: (1)取出16进制整数x的最高4个二进制位至y:y=x(16-4)&0xf。 (2)将该整数x(占2字节)左移4个二进制位: x=(x4)&0xffff。0,下一页,第10章 共用体与枚举类型,上一页,例10.1,分析:可先取出16进制整数的最高4个二进制位,然后将该整数左移4个二进制位,最后将先前取出的最高4个二进制位放入低4个二进制位位置。,#include “stdio.h” main( ) int x,y;printf(
12、“n请输入16进制整数:”);scanf(“%x”, ,请输入16进制整数:2fe1 循环左移4个二进制位得:fe12,第10章 共用体与枚举类型,(3)将先前取出的最高4个二进制位放入低4个二进 制位: x=x|y。,运行结果,返回,10.5 枚举类型,1. 枚举类型的定义,枚举类型定义用关键字enum标识,形式为: enum 标识符枚举数据表;标识符用来区分不同的枚举类型,定义的枚举类型用enum标识符”标识。 枚举数据(枚举常量)是一些特定的标识符, 标识符代表什么含义,完全由程序员决定。数据枚举的顺序规定了枚举数据的序号,从0开始,依次递增。,下一页,第10章 共用体与枚举类型,上一页
13、,(1) 定义枚举类型status, 包含复制与删除两种状态: enum status copy, delete; 枚举类型status仅有两个数据,一个是copy,一个是delete, 序号为0、 1, 代表复制与删除。,下一页,第10章 共用体与枚举类型,上一页,例如,(2) 定义枚举类型color,包含红、黄、蓝、白、黑五种颜色: enum color red, yellow, blue, white, black; 枚举类型color有red、 yellow、 blue、 white、 black五个数据, 序号为0、 1、 2、 3、 4, 代表红、 黄、 蓝、 白、 黑五种颜色。,
14、下一页,第10章 共用体与枚举类型,上一页,(3) 定义枚举类型weekday, 包含一周的七天: enum weekday sun, mon, tue, wed, thu, fri, sat; 枚举类型weekday有sun、 mon、 tue、 wed、 thu、 fri、sat七个数据, 序号为0、 1、 2、 3、4、 5、 6, 代表一周中的星期天、星期一、星期二、星期三、星期四、 星期五、星期六。 在定义枚举类型时,程序员可在枚举数据时通过“=”号自己规定序号,并影响后面的枚举数据的序号,后继序号以此递增。例如: enum statuscopy=6, delete; 则copy的序
15、号为6, delete的序号为7。,下一页,第10章 共用体与枚举类型,上一页,2. 枚举类型变量的定义,先定义枚举类型, 再定义枚举类型变量: enum 标识符 枚举数据表; enum 标识符 变量表; (2) 在定义枚举类型的同时定义枚举类型变量: enum 标识符 枚举数据表 变量表; (3) 直接定义枚举类型变量: enum 枚举数据表 变量表;,下一页,第10章 共用体与枚举类型,上一页,例如, 对枚举类型enum color, 定义枚举变量c1、 c2: enum color red, yellow, blue, white, black; enum color c1, c2; 或
16、enum color red,yellow,blue,white,black c1,c2; 或enum red, yellow, blue, white, black c1,c2;,下一页,第10章 共用体与枚举类型,上一页,枚举类型数据可以进行赋值运算。枚举类型是有序类型, 枚举类型数据还可以进行关系运算。枚举类型数据的比较转化成对序号进行比较, 只有同一种枚举类型的数据才能进行比较。,枚举类型数据不能直接输入输出。枚举类型数据输入时,先输入其序号,再进行强制类型转换完成。输出时,采用开关语句先进行判断,再转化成对应字符串输出。,下一页,第10章 共用体与枚举类型,上一页,使用强制类型转换,
17、可将整数值(枚举值序号)转换成对应枚举值。 例如: c1=(enum color )2; /*c1得到枚举值blue*/,将枚举型数据按整型格式输出,可得到整数值(枚 举变量值的序号)。 ,某口袋中有红、 黄、 蓝、 白、 黑五种颜色的球若干个,每次从口袋中取出三个球,问得到三种不同颜色的球有多少种取法,并输出每种组合结果。,不用枚举类型:,第10章 共用体与枚举类型,例10.4,点击,请,采用枚举类型来描述数据。设用red表示红色球,yellow表示黄色球,blue表示蓝色球,white 表示白色球, black表示黑色球。,点击,请,返回,10.6 类型定义,在使用标准类型定义或说明变量时
18、,可只写标准类型名指明变量数据类型。而用前面介绍的结构体、共用体、枚举等类型定义或说明变量时要冠以表明数据类型类别的关键字,如struct、union、enum等。C语言提供了用typedef定义类型,为类型命名的机制。用typedef定义新的类型名后,对于结构体、共用体或枚举类型,使用它们定义或说明变量时不必再冠以类型类别关键字。,下一页,第10章 共用体与枚举类型,上一页,1. 简单的名字替换,typedef int INTEGER; 意思是将int型定义为INTEGER,这两者等价,在程序中就可以用INTEGER作为类型名来定义变量了。例如: INTEGER x,y; 相当于int x,
19、 y;,下一页,第10章 共用体与枚举类型,上一页,2定义一个类型名代表一个结构体类型,typedef struct long num;char name20;float score; STUDENT; 将一个结构体类型 struct 定义为花括号后的名字STUDENT。可以用它来定义变量。 STUDENT student1,student2,*p;,下一页,第10章 共用体与枚举类型,上一页,例如,用typedef定义一个新类型名的方法如下: (1)先按定义变量的方法写出定义体(如char a20;)。 (2)将变量名换成新类型名(如char NAME20;)。 (3)在最前面加上typedef(如typedef char NAME20;)。 (4)然后可以用新类型名去定义变量(如NAME c,d;)。,下一页,第10章 共用体与枚举类型,上一页,用typedef定义类型,只是为类型命令,或为已有类型命名别名。作为类型定义,它只定义数据结构,并不要求分配存储单元。用typedef定义的类型来定义变量与直接写出变量的类型定义变量具有完全相同的效果。,例10.4,第10章 共用体与枚举类型,返回,