第10章位运算与枚举类型.ppt
程序设计技术,C语言数据描述和C程序设计初步 结构化程序设计基础和C语言的控制结构 数组及其应用 函数与C程序结构 指针与函数 指针与数组 字符串及其应用 结构体类型和联合体类型 C语言的文件处理及其应用 位运算与枚举类型,位运算与枚举类型,C语言的位运算及其应用 位段及应用 枚举数据类型及其应用,位运算,位运算的概念二进制位(Bit)二进制位(Bit)是计算机系统中能够表达的信息最小单位,一个二进制位能够表达出两个信息“0”和“1”。字节(byte)字节(byte)是计算机系统中的基本信息单位,一个字节由8个二进制位组成,其中最右边一位称为“最低有效位”,最左边的一位称为“最高有效位”。位运算注意点位运算的数据对象只能是整型类型兼容的数据;位运算中将参加位操作的数据对象(整型类型)拆开为二进制位看待。,位运算,位运算符C语言提供了下列11个用于位操作的运算符或复合运算符对程序设计中的位运算提供支持,位运算,按位与运算符(&)按位与运算符&是一个双目运算符;功能将参加操作的两个对象的各个位分别对应进行“与”运算,即:两者都为1时结果为1,否则结果为0;设有十进制整数:x=128、y=64,则:00000000000000000000000010000000(十进制数:128)&)00000000000000000000000001000000(十进制数:64)00000000000000000000000000000000(十进制数:0)运算结果:x&y=0。例10-1 按位与运算示例。,位运算,按位或运算符(|)按位或运算符|是一个双目运算符;功能将参加操作的两个对象的各个位分别对应进行“或”运算,即:两者都为0时结果为0,否则结果为1。设有十进制整数:x=128、y=64,则:00000000000000000000000010000000(十进制数:128)|)00000000000000000000000001000000(十进制数:64)00000000000000000000000011000000(十进制数:192)运算结果:x&y=192例10-2 按位或运算示例。,位运算,按位异或运算符()按位异或运算符是一个双目运算符;功能将参加操作的两个对象的各个位分别对应进行“异或”运算,即:两者值相同时结果为0,否则结果为1。设有十进制整数:x=128、y=64,则:00000000000000000000000010000000(十进制数:128))00000000000000000000000001000000(十进制数:64)00000000000000000000000011000000(十进制数:192)运算结果:x&y=192例10-3 按位异或运算示例。,位运算,按位取反运算符()按位取反运算符是一个单目运算符;功能将参加操作的对象的各个位进行“取反”操作,即:0变为1,1变为0。设有十进制整数:x=128,则:00000000000000000000000010000000(十进制数:128)x=11111111111111111111111101111111(十进制:4294967167)运算结果:x=4294967167例10-4 按位取反运算示例。,位运算,左移运算符()左移运算符是一个双目运算符;功能将参加操作的左操作对象的全部位向左移动右操作对象指定的位数,左移出去的数位丢失,左移后数的右边补0。设有十进制整数:x=128、移动位数为2,则:00000000000000000000000010000000(十进制数:128)x2 00000000000000000000001000000000(十进制数:512)运算结果:x2=512例10-5 左移运算示例。,位运算,左移运算符()左移位运算的特点数据对象进行左移操作时,只要没有出现溢出现象(即移位后的数据仍在取值范围之内),那么某数左移一位相当于将该数乘2;若在数据对象的左移操作中出现了溢出现象,则数据对象不能正确表示出来;设有十进制整数:x=128、移动位数为25,则:00000000000000000000000010000000(十进制:128)x25 100000000000000000000000000000000(十进制:0,最前面的1丢失),位运算,右移运算符()右移运算符是一个双目运算符;功能将参加操作的左操作对象的全部位向右移动右操作对象指定的位数,右移出去的数位丢失,右移后左边留下的空位填充取决于左操作对象的数据类型:对无符号数据(unsigned char和unsigned int),左边补0;对有符号数据(int和char)左边补其符号位,即正数补0、负数补1。,位运算,右移运算符()设有十进制整数:x=128、移动位数为2,则:00000000000000000000000010000000(十进制数:128)x2 00000000000000000000000000100000(十进制数:32)运算结果:x2=32,设有十进制整数:x=-128、移动位数为2,则:10000000000000000000000010000000(十进制:-128的原码)11111111111111111111111101111111(十进制:-128的反码)11111111111111111111111110000000(十进制:-128的补码)x2 11111111111111111111111111100000(十进制:-32的补码)10000000000000000000000000011111(十进制:-32的反码)10000000000000000000000000100000(十进制:-32的原码)-0000000000000000000000000100000(十进制数:-32)运算结果:x2=-32 例10-6 右移运算示例。,位运算,位运算应用举例例10-7 编程序实现将一个无符号整型数据二进制代码中811位取出的功能。问题分析:对处理的数据num通过num=8将其本身的07位移出,移位后num中原来的811位成为移位后数据的低4位;通过mask=(0 4)表达式构造一个除低4位为1,其余位都为0的整型数据mask;通过表达式num&mask得到一个低4位保留了num低4位值(即num最初的811位值)的整型数据并输出。,位运算,位运算应用举例例10-8 利用二进制位运算进行十进制整数到二进制数的转换。问题分析:从原理上说,十进制整数到二进制数的转换应该使用“除2取余法”。从前面的介绍得知,对整型数据而言在系统存储器中存储的是其二进制补码形式。如果被转换的十进制数是正数,则其补码与其原码相同,转换时只需要判断出最高位(符号位)以外的所有二进制位,二进制位值为1时输出1,二进制位值为0时输出0即可得到转换后的二进制数据。如果被转换的十进制数是负数,首先单独处理数据符号位,然后将其在存储器中的数据转换为对应的原码后再按正整数处理。,位运算与枚举类型,C语言的位运算及其应用 位段及应用 枚举数据类型及其应用,位段及应用,位段的概念和定义方法位段的概念:位段也可以称为“位域”、“位字段”等,是字节中一些位的组合,又可以称之为“位信息组”。位段实际上是一种特殊的结构体成员,不同的是它以位为单位来定义成员的长度。位段中成员的类型只能是整型(int)和无符号整型(unsigned int)。struct 标识符 位段成员定义;,位段成员的定义中不但要指定成员的名字,还需要指明成员所需要的二进制位数,其一般形式为:数据类型名变量名:二进制位数;,struct control unsigned a:3;unsigned b:1;unsigned c:3;control_data;,位段及应用,位段的概念和定义方法在结构体类型中可以混合定义位段和一般的结构体成员。定义位段时,可以跳过某些位不用,方法是在结构体类型中定义只指定了所占用二进制位数的特殊成员项。由于被跳过的这些位段没有名字,所以在程序中无法使用。,struct control int x;char name8;unsigned a:3;unsigned b:1;unsigned c:3;control_data;,struct control int x;char name8;unsigned a:3;unsigned:4;unsigned b:1;unsigned c:3;control_data;,位段及应用,位段的概念和定义方法定义位段时可以指定某些位段从一个新的字节开始起存放,方法是在该成员的前面定义一个二进制位数为0的成员。特别注意点:一个位段成员应该完整地存储在一个字节中。当一个字节所剩空间不够存放下一位段成员时,则应该跳过当前字节剩余的部分从下一字节单元起存放位段成员。,struct control int x;char name8;unsigned a:3;unsigned:0;unsigned b:1;unsigned c:3;control_data;,要求c占3个二进制位struct control unsigned a:3;unsigned b:3;unsigned:0;unsigned c:3;control_data;,位段及应用,位段的引用方法由于位段本质上是一种特殊的结构体类型数据,所以位段成员的引用方法与引用结构体变量的成员分量方法相同,即需要用点运算符连接结构体变量和位段成员名。位段可以赋值,但在赋值操作时必须注意一个位段成员分量的取值范围(即能够存储的最大值)。可以通过指向含有位段成员的结构体变量引用该结构体变量的地址,也可以通过指针变量来引用位段。特别注意:由于位段成员存储是以二进制位为单位而不是以字节为单位,所以不能象引用结构体变量中的普通成员地址那样引用位段成员的地址。例10-9 实现一个洗牌和发牌的模拟程序,要求在程序的实现过程中尽可能减少所需要的存储空间。,位运算与枚举类型,C语言的位运算及其应用 位段及应用 枚举数据类型及其应用,枚举数据类型及其应用,枚举的概念语言中提供了“枚举”数据类型对上面的程序设计要求予以支持。在“枚举”数据类型的定义中列举出其变量所有可能的取值,被说明为该“枚举”类型的变量取值不能超过定义的范围。枚举类型是一种基本数据类型而不是构造类型,因为它不能再分解为任何基本类型。程序中设计中使用枚举这类 在某种意义上可以描述数据对象物理含义的数据比用阿拉伯数字使得程序更加清晰并容易理解。,枚举数据类型及其应用,枚举类型和枚举类型变量的定义枚举数据类型定义的一般形式为:enum标识符枚举值列表;enum是C语言中定义枚举数据类型的关键字,它和其后的标识符一起构成了枚举数据类型的类型名字;枚举值列表中列出的是对该枚举数据类型变量取值的规定范围,这些值也称为枚举元素,在定义枚举类型时枚举元素必须使用合法的标识符予以表示。,例:定义数据类型名为enumWeekday的枚举数据类型enumWeekdayMonday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday;,枚举数据类型及其应用,枚举类型和枚举类型变量的定义对于枚举数据类型也需要定义枚举变量后才能使用,枚举变量的定义有如下3种方法:先定义枚举数据类型,再定义枚举类型变量在定义枚举数据类型的同时定义枚举类型变量只定义几个某种枚举数据类型的枚举变量,enumWeekdayMonday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday;typedef enum Weekdat WEEK;WEEKa,b,c;,enumWeekdayMonday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sundaya,b,c;,enumMonday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sundaya,b,c;,定义枚举数据类型还需要特别注意下面两点 枚举元素必须用C语言的合法标识符表示;枚举定义中的标识符必须惟一;,枚举数据类型及其应用,枚举常量在C语言中,枚举是用标识符表示的整型常量的集合,即枚举常量是自动设置整型数值的符号常量。默认情况下枚举常量的起始值为0,以后的每个枚举元素值递增1。在定义枚举类型时可以指定某一枚举元素的起始值,并从此处开始,以后的每个枚举元素值递增1。可以在枚举类型定义中对枚举元素表示的起始值作多次改变,每一个改变后枚举值从该之开始递增到遇到下一次指定起始值为止。,enumWeekdayMonday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday;标识符被自动设置为与整型数0到6对应,enumWeekdayMonday=1,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday;标识符被自动设置为与整型数1到7对应,enumWeekday Thursday=4,Friday,Saturday,Sunday,Monday=1,Tuesday,Wednesday;从Thursday到Sunday的枚举常量值依次为4、5、6和7,接着的Monday到Wednesday的枚举常量值依次为1、2和3,枚举数据类型及其应用,枚举的应用枚举变量的使用时必须注意下面几点:不能直接输入/输出枚举变量的值;不能将枚举元素对应的整型数值直接赋予枚举变量;不能在程序中试图修改枚举元素的值例10-10 枚举变量的输入输出示例。例10-11 某网络中心需要安排部门技术人员值班,该中心负责值班有4位技术人员:张广生、李中士、王义、吴俊民。请编程序为他们安排125天轮流值班表。例10-12 编程序实现功能:模拟与计算机打扑克牌过程,要求从键盘上输入1张牌值,含花色(suit)和面值(face),让计算机随机产生1张牌,比较2张牌的大小。,