《C第2版(第11章_位运算)》由会员分享,可在线阅读,更多相关《C第2版(第11章_位运算)(20页珍藏版)》请在金锄头文库上搜索。
1、C语言程序言程序设计教程教程(第(第2版)版)第第1111章章 位运算位运算本章主要内容本章主要内容1.1.按按位取反位取反运算运算2.2.按按位左移位左移运算运算3.3.按按位左移位左移运算运算4.4.按按位与位与运算运算5.5.按按位或位或运算运算6.6.按按位异或位异或运算运算7.7.复合位运算复合位运算第第1111章章 位运算位运算11.1 位运算符位运算符 C 既具有高级语言的特点,又具有低级语言的功能,既具有高级语言的特点,又具有低级语言的功能,位运算能力就是其特色之一。所谓位运算能力就是其特色之一。所谓位运算位运算就是指进行二就是指进行二进制位的运算。进制位的运算。C提供的位运算
2、符有:提供的位运算符有:运算符运算符 含义含义 &按位与按位与 按位或按位或 按位异或按位异或 取反取反 右移右移说明:说明: 位位运运算算符符中中除除“”外外,其其余余均均为为二二目目运运算算符符,即即要要求求两侧各有一个运算量。两侧各有一个运算量。 运运算量只能是整型或字符型的数据算量只能是整型或字符型的数据,不能为实型数据。,不能为实型数据。11.2 “按位与按位与” 运算符运算符 & 参参加加运运算算的的两两个个运运算算量量之之对对应应位位都都为为1,则则该该位位的的结结果为果为1,否则为,否则为0。即:。即:0&0=0 0&1=0 1&0=0 1&1=1例例: 3&5=13的补码:的
3、补码: 000000115的补码:的补码: 00000101& 00000001& 运算符的用途:运算符的用途: 清零清零 如如果果想想将将一一个个单单元元清清零零(全全部部二二进进位位为为 ),则则只只要要找找一一个个数数的的补补码码的的对对应应位位0与与被被清清零零数数的的对对应应位位1刚刚好好对对应应,然后使两者进行然后使两者进行 & 运算。运算。如:如:00101011 & 1001010000000000 取一个数中的某些指定位取一个数中的某些指定位如:如: a:0010110010101100b:0000000011111111 (377)8& 0000000010101100 得
4、到得到 a 的低的低 8 位位 保留一个数的某一位保留一个数的某一位如:如: 01010100 (84)10 & 00111011 (59)1000010000 (16)1011.3 “按位或按位或”运算符运算符 参参加加运运算算的的两两个个运运算算量量之之对对应应位位只只要要有有一一个个为为1,则该位的结果为则该位的结果为1。即:。即: 0 0 = 0 0 1 = 1 1 0 = 1 1 1 = 1如:如:00110000 (060)8 00001111 (017)800111111 (077)8 即一个数与即一个数与017进行按位或运算,就可将该数的低进行按位或运算,就可将该数的低4位全置
5、为位全置为1;与;与0377进行按位或运算,就可将该数的低进行按位或运算,就可将该数的低8位全置为位全置为1。11.4 “异或异或”运算符运算符 参参加加运运算算的的两两个个运运算算量量的的对对应应位位相相同同,则则该该位位的的结结果为果为0。否则为。否则为1。即:。即: 0 0 = 0 0 1 = 1 1 0 = 1 1 1 = 0如:如: 00111001 (57)10 、(071)8 00101010 (42)10 、(052)800010011 (19)10 、(023)8 运算符的用途:运算符的用途:使指定的位翻转使指定的位翻转如:如: 01111010 00001111 对应原数的
6、低对应原数的低4位均置为位均置为101110101 原数的低原数的低4位被翻转位被翻转若若 a=3, b=4。则则a=a b; b=b a;a=a b;结果是什么?结果是什么?交换两个值,不用临时变量例如:,。想将和的值互换,可以用以下赋值语句实现:ab;ba;ab; () (ab的结果,a已变成)() (ba的结果,b已变成)() (ab的结果,a已变成)11.5 “取反取反” 运算符运算符 运算是对一个二进制数按位取反,即将运算是对一个二进制数按位取反,即将0变为变为1,1变为变为0。8位全位全1用用377;16位全位全1用用177777;32位全位全1用用37777777777。11.6
7、 “左移左移”运算符运算符 用来将一个数的各二进制位全部左移若干位,并在用来将一个数的各二进制位全部左移若干位,并在右边补若干个右边补若干个0。高位左移后溢出,舍弃不起作用。如:。高位左移后溢出,舍弃不起作用。如: 用来将一个数的各二进制位全部右移若干位,移用来将一个数的各二进制位全部右移若干位,移到右边的低位被舍弃,对无符号数,高位补到右边的低位被舍弃,对无符号数,高位补0。如:如: a 为为00001111,则,则 a2为为00000011 11右移一位相当于除以右移一位相当于除以2 ,右移,右移 n 位相当于除以位相当于除以2 n。(此此 2 位被舍弃位被舍弃)注意:注意:在右移时,需要
8、注意符号位问题。若为无符号数,在右移时,需要注意符号位问题。若为无符号数,右移时左边高位移入右移时左边高位移入0。若为有符号数,如果原来符号位。若为有符号数,如果原来符号位为为0 (正数正数),则左边移入,则左边移入0 ;如果原来符号位为;如果原来符号位为1 ,左边,左边移入移入0的称为的称为“逻辑右移逻辑右移” ,移入,移入1的称为的称为“算术右移算术右移”。大多数大多数C语言均采用算术移位。语言均采用算术移位。如:如: a:1001011111101101 (113755)8a1:0100101111110110 逻辑右移逻辑右移, 得得045766a1:1100101111110110
9、算术右移算术右移, 得得14576611.8 程序范例程序范例例例11.1 取一个整数取一个整数 a 从右端开始的从右端开始的 4 7 位。位。步骤步骤: 先使先使 a 右移右移 4 位。即:位。即: a(7 4 + 1 ) a4 设置一个低设置一个低4位全为位全为1,其余全为,其余全为0 的数。即:的数。即: ( 0 4 ) 将两者进行将两者进行 & 运算运算未右移时的情况 右移4位后的情况 #include main( )unsigned a, b, c, d ; scanf(%o, &a); b = a4;/* b=a(m-n+1) */ c = (04);/* c=(0n) */ d
10、= b&c; printf(%on%on, a, d );运行情况:运行情况:331 33115例例11.2 循环移位。将循环移位。将 a 右循环移右循环移 4 位。位。 将将a的右端的右端 n 位放到位放到b的高端的高端n位中。位中。 b = a n ; 将将c与与b进行按位或运算。进行按位或运算。 c = c bmain( )unsigned a,b,c; int n; scanf(“a=%o,n=%d”,&a,&n); b = an; c = c b; printf(“%on%on”,a,c);运行情况:运行情况:a=157653, n=3 157653 (110111111010101
11、1)275765 (0111101111110101)211.9 位段位段 有时存储一个信息不必用一个或多个字节,可以在有时存储一个信息不必用一个或多个字节,可以在一个字节中存放几个信息。例如一个字节中存放几个信息。例如, “真真”或或“假假”用用1或或 0 表示,只需要表示,只需要 1 位就够了。位就够了。一、一、 在一个字节中存放几个数据在一个字节中存放几个数据图中:图中:a、b、c、d分别占分别占2位、位、6位、位、4位、位、4位。假定位。假定c 原来的值为原来的值为0,现要变为,现要变为12,则:,则: 将数将数 12 左移左移 4 位,使位,使 1100 成为右边起第成为右边起第 4
12、7 位。位。 将将 data 与与 124 按按位位或或即即可可(设设 data 中中第第 47 位位原来为原来为0 )。若若 c 的原值不为的原值不为0 ,则应先使,则应先使 c 为为0。方法如下:。方法如下:data = data & 01774170177417 称为称为“屏蔽字屏蔽字”当当然然也也可可以以用用:data=data & (154) 来来实实现现,而而不必计算屏蔽码。从而可以得到:不必计算屏蔽码。从而可以得到:data=data & (154)(n&15)4; / n为为赋赋给给c的的值值 /二、二、 位段位段 位段是以位为单位定义长度的结构体类型中的成员。位段是以位为单位
13、定义长度的结构体类型中的成员。struct packed_data unsigned a: 2; unsigned b: 6; unsigned c: 4; unsigned d: 4; int i;data;结构体中结构体中 a、b、c、d 共占共占 2 个字节,个字节,i 占占2个字节。个字节。几点说明:几点说明: 位位段段也也是是一一种种结结构构体体分分量量,其其引引用用方方法法与与结结构构体体相相同同。如:如:data .a = 2;data .b = 3; 长长度度为为 的的位位段段可可以以使使其其后后的的位位段段从从下下一一个个存存储储单单元元开始存放。如:开始存放。如:unsig
14、ned a: 1;unsigned b: 2; / 在一个存储单元在一个存储单元 /unsigned : 0;unsigned c: 3; / 另一个存储单元另一个存储单元 /必须注意位段分量允许的最大取值范围必须注意位段分量允许的最大取值范围。允许允许不允许不允许 一个位段不得跨一个位段不得跨 2 个存储单元。如:个存储单元。如:unsigned a : 6;unsigned a : 6;unsigned a : 5;unsigned a : 6;unsigned a : 6;unsigned : 0;unsigned a : 5; 可以定义无名位段。如:可以定义无名位段。如: unsign
15、ed a : 1; unsigned : 2; unsigned b : 3; 一个位段的长度不得大于一个存储单元的长度,也不能定一个位段的长度不得大于一个存储单元的长度,也不能定义位段数组。义位段数组。 位段可以用整型格式符输出。如:位段可以用整型格式符输出。如: printf(“%d, %d, %d”, data.a, data.b, data.c);也可以用也可以用%u, %o, %x 等格式符输出。等格式符输出。 位位段段可可以以在在数数值值表表达达式式中中引引用用,它它会会被被系系统统自自动动地地转转换换成成整型数。如:整型数。如:data.a + data.b 是合法的。是合法的。1.1.单操作数参与的位运算符单操作数参与的位运算符 取反取反 右移右移2. 2. 多操作数参与的位运算符多操作数参与的位运算符&按位与按位与 按位或按位或 按位异或按位异或3. 位运算的应用位运算的应用本章重点本章重点习习 题题一、单选题一、单选题二、判断题二、判断题三、填空题三、填空题四、编程题四、编程题【题题1111.31 1】 【题题11.3211.32】 【题题11.3411.34】 【题题11.3711.37】 【题题11.3811.38】 【题题11.3911.39】全部全部