1、9.4 9.4 共共 用用 体体 1共用型概念共用型概念 使几个不同的变量占用同一段内存空间的结构称为共使几个不同的变量占用同一段内存空间的结构称为共用型。用型。2共用类型的定义共用类型的定义与结构类型的定义类似与结构类型的定义类似 union 共用类型名共用类型名 成员列表成员列表 ;3共用变量的定义共用变量的定义与结构变量的定义类似与结构变量的定义类似 直接定义形式如下:直接定义形式如下:间接定义形式如下:间接定义形式如下:union union 共用体名共用体名 union union 共用体名共用体名 分量表分量表 分量表分量表 ;变量表变量表;union union 共用体名共用体名
2、 变量表变量表;共用变量的引用共用变量的引用与结构变量一样只能逐个引用共用变量的成员与结构变量一样只能逐个引用共用变量的成员 printf(“%d”,a);错误错误 scanf(“%d”,&a);错误错误访问变量访问变量 a 各成员的格式为:各成员的格式为:a.i、a.ch、a.f scanf(“d”,&a.i);printf(“%dn”,a.i);5.共用体与结构体相似之处共用体与结构体相似之处(1 1)都是由不同类型的数据项组成一个都是由不同类型的数据项组成一个(2 2)都只能对分量进行操作和引用。都只能对分量进行操作和引用。例例 1:对共用体变量的使用对共用体变量的使用struct in
3、t num;编号编号 char name10;姓名姓名 char sex;性别性别 char job;类别:类别:s 学生学生 t 教师教师 union int ciass;班号班号 char position10;职务职务 category;per 2;构造类型构造类型(数组、数组、结构体、共用体结构体、共用体)的定义可以嵌套的定义可以嵌套 main()int n,i;for(i=0;i2;i+)scanf(“%d%s%c%c”,&peri.num,peri.name,&peri.sex,&peri.job);if(peri.job=s)scanf(“%d”,&peri.category.c
4、lass);else if(peri.job=t)scanf(“%s”,peri.category.position);else printf(“input error!”);prints(“n”);6共用变量特点共用变量特点(1)系统采用覆盖技术,实现共用变量各成员的内系统采用覆盖技术,实现共用变量各成员的内存共享,所以在某一时刻,存放的和起作用的是最后一次存共享,所以在某一时刻,存放的和起作用的是最后一次存入的成员值。存入的成员值。(2)由于所有成员共享同一内存空间,故共用变量由于所有成员共享同一内存空间,故共用变量与其各成员的地址相同。与其各成员的地址相同。(3)不能对共用变量进行初始化
5、(注意:结构变量不能对共用变量进行初始化(注意:结构变量可以);也不能将共用变量作为函数参数,以及使函数返可以);也不能将共用变量作为函数参数,以及使函数返回一个共用数据,但可以使用指向共用变量的指针。回一个共用数据,但可以使用指向共用变量的指针。(4)共用类型可以出现在结构类型定义中,反之亦共用类型可以出现在结构类型定义中,反之亦然。然。struct memb float v;int n;char c;sa1;sa1占占7个字个字 节内存空间节内存空间union memb float v;int n;char c;usa2;usa2占占4个字个字节节内存空间内存空间 100110051007
6、vnc2001vnc200220032004 共用变量占用的内存空间,等于最长成员的长度,而共用变量占用的内存空间,等于最长成员的长度,而不是各成员长度之和。不是各成员长度之和。7、共用体与结构体的主要区别共用体与结构体的主要区别 (1 1)结构体变量结构体变量 占用空间是各成员所占空间之总和占用空间是各成员所占空间之总和;共用体变量共用体变量 占存储空间是各成员中所占空间最大者。占存储空间是各成员中所占空间最大者。(2 2)结构体变量结构体变量 各成员占用内存中一片连续的存储区,各成员占用内存中一片连续的存储区,各成员的地址互不相同;各成员的地址互不相同;共用体变量共用体变量各成员在内存中所
7、占各成员在内存中所占空间的起始地址相同。空间的起始地址相同。(3 3)结构体变量结构体变量的各个分量在任何时刻都同时存在,的各个分量在任何时刻都同时存在,且可同时引用。且可同时引用。共用体变量共用体变量的各个分量在同一时刻只存在的各个分量在同一时刻只存在其中一个,也只能引用其中的一个其中一个,也只能引用其中的一个。(4 4)结构体变量结构体变量可以初始化可以初始化,共用体变量共用体变量不能初始化。不能初始化。例例2:共用体的内存使用。共用体的内存使用。#include void main()union int i;char string2;a;a.i=24897;printf(“i=%d,st
8、ring1=%c”,a.i,a.string0);printf(“string2=%cn”,a.string1);string0=0;string1=0;printf(“i=%d,string1=%c”,a.i,a.string0);printf(“string2=%cn”,a.string1);程序运行结果程序运行结果:i=24897,string1=A,string2=ai=8224,string1=0,string2=0例例3:将共用体变量作为函数的参数。将共用体变量作为函数的参数。#include union testint i;char string2;a;void show(uni
9、on test a)printf(“i=%d,string1=%c”,a.i,a.string0);printf(“string2=%cn”,a.string1);return;void main()a.i=24897;show(a);string0=0;string1=0;show(a);return;程序运行结果:程序运行结果:I=24897,string1=A,string2=aI=8224,string1=0,string2=01定义格式:定义格式:enum 枚举类型名枚举类型名 取值表取值表;例如,例如,enum weekdays Sun,Mon,Tue,Wed,Thu,Fri,Sa
10、t;中的标识符称为枚举常量。中的标识符称为枚举常量。它只能为标识符,不能为数字常量或字符常量它只能为标识符,不能为数字常量或字符常量2枚举变量的定义(与结构体变量类似)枚举变量的定义(与结构体变量类似)(1)间接定义)间接定义例如,例如,enum weekdays w1,w2;(2)直接定义直接定义例如,例如,enum weekdays Sun,Mon,Tue,Wed,Thu,Fri,Sat w1,w2;9.5 9.5 枚枚 举举 类类 型型3枚举型使用说明枚举型使用说明(1)枚举型仅适应于取值有限的数据。枚举型仅适应于取值有限的数据。例如例如:周天周天,年个月。年个月。(2)取值表中的值为枚
11、举元素,其含义由程序解取值表中的值为枚举元素,其含义由程序解释。释。例如,不是写成例如,不是写成“Sun”就自动代表就自动代表“星期天星期天”。事实上,事实上,枚举元素用什么表示都可以。枚举元素用什么表示都可以。(3)枚举型变量枚举型变量 w1,w2 只能在定义的值表中取只能在定义的值表中取其中一个枚举常量作为当前值。其中一个枚举常量作为当前值。(4)枚举元素作为常量是有值的。枚举元素作为常量是有值的。定义时定义时顺序号,从开始顺序号,从开始,所以枚举元素可以进行,所以枚举元素可以进行比较,比较规则是:序号大者为大!比较,比较规则是:序号大者为大!例如,上例中的例如,上例中的Sun=0、Mon
12、=1、Sat=6,所以所以 MonSun、Sat 最大。最大。(5)枚举元素的值也是可以改变的。枚举元素的值也是可以改变的。在定义时由程序指定,例如在定义时由程序指定,例如:enum weekdays Sun=7,Mon1,Tue,Wed,Thu,Fri,Sat;则则Sun=7,Mon=1,从从Tue=2开始,依次增。开始,依次增。(6)一个整型数值不能直接赋值给一个枚举变量。一个整型数值不能直接赋值给一个枚举变量。enum weekdays Sun=7,Mon 1,Tue,Wed,Thu,Fri,Sat;enum weekdays wk1;不允许直接赋值整数:不允许直接赋值整数:wk1=7;
13、/*数据类型不同数据类型不同*/只能写成:只能写成:wk1=Sun;或:或:wk1=(enum weekdays)7;甚至可以是表达式,如:甚至可以是表达式,如:w2=(enum weekday)(5-3);例例 4:枚举类型的用法枚举类型的用法#include enum months JAN=1,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC;main()enum months month;char*mname=,January,February,March,April,May,June,July,Auguest,September,October,N
14、ovember,Dcember;for(month=JAN;month=DEC;month+)printf(%2d-%-10sn,month,mnamemonth);9.6 9.6 typedef typedef 类型定义类型定义 除可直接使用提供的标准类型和自定义的类型除可直接使用提供的标准类型和自定义的类型(结构、共用、枚举)外,也可使用(结构、共用、枚举)外,也可使用typedeftypedef定义已有类定义已有类型的别名。该别名与标准类型名一样,可用来定义相应型的别名。该别名与标准类型名一样,可用来定义相应的变量的变量。()()简单的名字替换简单的名字替换typedef char CH
15、ARACTER;经过上面的定义后经过上面的定义后CHARACTER就与数据类型就与数据类型char等等价,同样也可以用价,同样也可以用CHARACTER来定义字符型变量。例来定义字符型变量。例如:如:typedef char CHARACTER;char a;CHARACTER b;变量变量a,b都是字符型。都是字符型。()()定义一个类型名代表一个结构体类型。例如;定义一个类型名代表一个结构体类型。例如;typedef struct char number9;char name8;char department50;STUDENT;STUDENT stud1,stud2;上面定义的变量上面定
16、义的变量stud1stud1和和stude2stude2都属于结构体变量,都属于结构体变量,这样就简单化了结构体变量的声明。这样就简单化了结构体变量的声明。typedef int *zzbl;zzbl p,a6;等价于等价于 int *p,*a6;/*p是整型指针变量,是整型指针变量,a是整型指针数组是整型指针数组*/说明:说明:(1)用用typedef只是给已有类型增加个别名,并只是给已有类型增加个别名,并不能创造个新的类型。不能创造个新的类型。(2)typedef与与#define有有相似之处,但二者是不同相似之处,但二者是不同的:前者是由编译器在编译时处理的;后者是由编译的:前者是由编译
17、器在编译时处理的;后者是由编译预处理器在编译预处理时处理的,而且只能作简单的预处理器在编译预处理时处理的,而且只能作简单的字符串替换。字符串替换。9.9.7 7 位运算位运算 1、位逻辑运算符、位逻辑运算符 按位取反按位取反(与与!同级同级)单目右结合单目右结合&按位与按位与 按位异或按位异或 相同取相同取0,不同取,不同取1|按位或按位或1、位逻辑运算符 按位取反按位取反&按位与按位与 按位异或按位异或 相同取相同取0,不同取,不同取1|按位或按位或 x=0 00000000 00000000 y=3 00000000 00000011x&y 00000000 00000000 x|y 00
18、000000 00000011xy 00000000 000000111010 0101=1111 注意区分:注意区分:&和和|&和和|x&y得得 0 x|y得得 12、位移位运算符 对操作数右移给出的位数对操作数右移给出的位数 x3 将将x向向左移左移3位,空出的位用零填补位,空出的位用零填补 00111010 3 将将x向右移向右移3位位 00111010 3 000001113、复合位赋值运算符&=|=例:例:a&=b 相当于相当于 a=a&b a=2 相当于相当于 a=a29.8 9.8 宏定义宏定义#define 宏名标识符 宏定义字符串编译编译时,把程序中所有与宏名相同的字符串,用宏定义字符串替代替代。#define PI 3.14#define arr_size 4带参数的宏定义带参数的宏定义例:用宏实现两个变量值的交换#define f(a,b,t)t=a;a=b;b=t;void main()int x,y,t;scanf(“%d%d”,&x,&y);f(x,y,t)printf(“%d%dn”,x,y);t=x;x=y;y=t;编译时被替换注意注意:(1)带参数的宏定义不是函数,宏与函数是两种不同的概念。(2)宏可以实现简单的函数功能