250 likes | 330 Views
位运算. 10. 10. 位运算. 【 导读 】. 本 部分介绍 C 语言提供的位运算功能,是 C 语言具有某些低级语言的特性之一,与其他高级语言相比,具有很大的优越性。 通过本章的学习,要求掌握基本位运算的形式,掌握位运算的一般性计算方法及其应用。. 10.1 几个基本概念. 【 问题 】 我们知道任何信息在计算机中都是以二进制形式表示,而我们日常生活中使用的是十进制,由于位运算是 对数据的二进制位进行运算 ,因此在学习位运算之前我们有必要回顾一下计算机内数据用二进制存储的形式。. 10.1.1 字节与位.
E N D
位运算 10
10.位运算 【导读】 本部分介绍C语言提供的位运算功能,是C语言具有某些低级语言的特性之一,与其他高级语言相比,具有很大的优越性。 通过本章的学习,要求掌握基本位运算的形式,掌握位运算的一般性计算方法及其应用。
10.1 几个基本概念 【问题】我们知道任何信息在计算机中都是以二进制形式表示,而我们日常生活中使用的是十进制,由于位运算是对数据的二进制位进行运算,因此在学习位运算之前我们有必要回顾一下计算机内数据用二进制存储的形式。
10.1.1字节与位 字节(byte)是计算机存储的基本单元。一个字节可以存放一个英文字母或符号,一个汉字通常要用两个字节来存储。 内存的每一个字节都有自己的编号,叫做“地址”。 一个字节由8个二进制位(bit)构成,每位的取值为0或1。最右端的那一位称为“最低位”,最左端的那一位称为“最高位”。为了便于称呼,从最低位到最高位依次编号为0、1、2…7。
10.1.1字节与位 计算机中用若干个字节存放一个数据或指令,它们组成一个单元叫做“字” (word)。 至于一个字由几个字节组成,取决于计算机的硬件系统。一般由1个、2个或4个字节组成,所对应的计算机也被称为“8位机、16位机或32位机”。目前的微机以32位机为主。 为了简单,本章讨论的数据大多用一个字节表示。下面介绍二进制数的几种编码方法。
请自行阅读如下内容:10.1.2 原码10.1.3反码10.1.4补码
10.2 位运算符和位运算 1、位逻辑运算符(附录C,P285),按优先级顺序为: ~(按位取反,单目,优先级最高) &(按位与) ^(按位异或) 双目,高于逻辑运算符,低于关系运算符 ¦ (按位或) 2、移位运算符:<<左移运算符、>>右移运算符, 同级,双目,低于算术运算符,高于关系运算符。 3、位运算自反赋值操作运算符(P286)优先级与赋值类一致: <<=、>>=、&=、^=、¦=
x y x&y x|y x^y ~y 0 0 0 0 0 1 0 1 0 1 1 0 1 0 0 1 1 1 1 1 1 1 0 0 10.2 位运算符和位运算 4、位逻辑运算符的运算 注意:位逻辑运算是对数据的每个二进制位进行的,双目运算符&、|和^是对两个数据的所有对应位进行的(表中只列出其中的一位),这不同于逻辑运算符(&&、||和!)是对整个数据运算。
10.2.1按位取反 【运算符】~ 【格式】~x 【功能】使x的各位翻转,即原来为1的位变成0,原来为0的位变成1。 【示例】如有unsigned char x=83,y=~x,则y=172。 83(01010011) ~83(~01010011) 172(10101100)
10.2.2按位与 【运算符】& 【格式】x&y 【功能】当两个操作对象二进制数的相同位都为1时,结果数值的相应位为1,否则相应位为0。 【主要用途】假定x是原数,y是“工具”数,结果相对于原数而言(其实是相互的),则&运算后: Y中为1的位使x中的对应位保留原值,同时Y中为0的位使x中的对应位清0,因此&可以用作: (1)将数x的某(些)位清0 (y的某(些)位为0,其余位为1) (2)保留(取)数x的某(些)位 (y的某(些)位为1,其余位为0)
10.2.2按位与 【例1】如x=0xb6,y=0xf0,z=x&y,则z=0xb0 x: 10110110 & y: 11110000 z=x&y: 10110000 即保留(取)前4位,后4位清0 【例2】如x=0124,想保留它的第0、1、3、4、5位,则取y=073,z=x&y,则z=020 x: 01010100 & y: 00111011 z=x&y: 00010000
10.2.3按位或 【运算符】| 【格式】x | y 【功能】当两个操作对象二进制数的相同位都为0时,结果数值的相应位为0,否则相应位为1。 【主要用途】对x、y的描述同按位与,则|运算后: Y中为1的位使x中的对应位置1,同时Y中为0的位使x中的对应位保留原值,因此|可以用作: 将数x的某(些)位置1 ,其余位不变(y的某(些)位为1,其余位为0)
10.2.2按位或 【例】如x=0xb6,y=0xf0,z=x|y,则z=0xf6 x: 10110110 | y: 11110000 z=x|y: 11110110 即前4位置1,后4位不变
10.2.4按位异或 【运算符】^ 【格式】x ^ y 【功能】当两个操作对象二进制数的相同位的值不同时,结果数值的该位为1,相同则该位为0。 【主要用途】对x、y的描述同按位与,则^运算后: Y中为1的位使x中的对应位翻转,同时Y中为0的位使x中的对应位保留原值,因此^可以用作: (1)将数x的某(些)位翻转,其余位不变(y的某(些)位为1,其余位为0)
10.2.2按位异或 【例】如x=0xb6,y=0xf0,z=x^y,则z=0x46 x: 10110110 ^ y: 11110000 z=x^y: 01000110 即前4位翻转,后4位不变 (2)不用临时变量,交换两个变量的值,如a=3,b=5 执行a=a^b; b=b^a; a=a^b;即可: a=00000011 ^ b=00000101 a=a^b=00000110 ^ b=00000101 b=b^a=00000011 /*b已经存放a原来的值*/ ^ a=00000110 a=a^b=00000101 /*a已经存放b原来的值*/
10.2.5 左位移 【运算符】<< 【格式】x<<n /* n为要将x左位移的位数 */ 【功能】把操作对象x的二进制数向左移动n位,并在右边补上n位的0,左边高n位则溢出。 【示例】如x=00000100,y=x<<2,则y=00010000, 即x=4,y=x<<2则y=16,相当于y=x*22。 【注意】左移引起数据的变化为:当不溢出时左移一位相当于对原来的数值乘以2,左移n位相当于对原来的数值乘以2n:a<<n==a*2n ;若溢出将取28(256,字符型)或216(65536,整型)等为模。 例如:x=01101100,y=x<<2,则y=10110000, 左边两位01溢出(x=108,y=432%256=176)。
10.2.6右位移 【运算符】>> 【格式】x>>n /* n为要将x右位移的位数 */ 【功能】把操作对象x的二进制数向右移动n位,移出的低n位舍弃(变成小数) ,高n位: (1) 对无符号数补0; (2) 对有符号数补符号位,正数也补0 ,称为“逻辑右移”;负数补1,称为“算术右移”。 【注意】右移引起数据的变化是:右移一位相当于对原来的数值除以2。右移n位相当于对原来的数值除以2n (正负数均成立)。
10.2.6右位移 【例1】如有char x=83, y; y=x>>2; 即:x为01010011, 右移两位为00010100,即y=20, 相当于83/22取整,本例实现了“逻辑右移”。 【例2】如有char x=-92, y; y=x>>2; 即:x的补码为10100100 (十进制为164), 右移两位为11101001 (十进制为233,即y的补码) , 也就是y=-23=-92/4,本例实现了“算术右移”。
说 明 (1) x、y和“位数”等操作数,都只能是整型或字符型数据。 (2)除按位取反为单目运算符外,其余均为双目运算符。 (3) 计算位逻辑运算结果时,操作数x和y都必须首先转换成二进制形式,然后再执行相应的位运算;计算移位运算时,被移位的操作数x必须首先转换成二进制形式。 例如,5<<2→20即00000101<<2→00010100, 20>>2→5即00010100>>2→00000101。
说 明 (4) 复合赋值位运算符 除按位取反运算外,其余5个双目位运算符均可与赋值运算符一起,构成复合赋值位运算符: &=、|=、^=、<<=、>>=。 例如:a &= b相当于 a = a & b。 a <<= 2相当于:a = a << 2。 (5)位运算混合运算时,按优先级的次序进行: ~ →<<和>> →& →^ →| →复合赋值位运算符 例如:a ^ b | ~c & d>>2 ① ② ④ ③ ⑤
说 明 (6) 不同长度数据间的位运算──最低位对齐,短数按长数的字节数补位,具体方法是: ① 对无符号数和有符号数中的正数,补0; ② 对有符号数中的负数,补码的高字节所有位全部补1 (以保持数值不变)。
10.3 程序举例 【例10-1】取一个整数a从右端开始的4~7位。 main(){unsigned a,b,c,d; scanf(“%o”,&a); b=a>>4; c=~(~0<<4); /*或者c=15;*/ d=b&c; printf("%o,%d\n%o, %d\n",a,a,d,d);}
【例10-2】从键盘上输入一个正整数给int型变量num,按二进制位输出该数【例10-2】从键盘上输入一个正整数给int型变量num,按二进制位输出该数 #include “stdio.h“main(){ int num, mask, i; printf(”Input a integer number:”); scanf(“%d”,&num); mask = 1<<15; printf(“%d=” , num); for(i=1; i<=16; i++) { putchar(num&mask ? ‘1’: ‘0’); num <<= 1; if( i%4==0 ) putchar(‘,’); } printf(“\bB\n”); /*用\b的目的是消除最后一个“,” */}
小结 本部分介绍的位运算在系统软件开发与计算机检测和控制领域中有重要应用,也是C语言的特色之一。重点要求读者掌握位运算符及其应用。 学好位运算必须了解计算机内数据的组织与存储形式,二进制及其补码的原理是关键。 本部分介绍的位运算包括按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)、右移(>>),实质上都是1和0的变换或者移动,学好位运算对今后计算机系统的编程很有好处。
结束 结束