首页 百科知识 c语言移位运算符怎么用

c语言移位运算符怎么用

时间:2023-10-17 百科知识 版权反馈
【摘要】:①位逻辑运算符是针对二进制位的,而逻辑运算符是针对整个表达式的;位逻辑运算符要计算表达式的具体数值,而逻辑运算符只判断表达式的真与假。由移位运算符和运算分量构成的表达式称为移位表达式。其中,“表达式1”是移位对象,“表达式2”是表示移位的位数。

2.4.5 位运算符和位表达式

位运算是指进行二进制位的运算。在C语言中,位运算符有位逻辑运算符和移位运算符。为了使没有学过汇编语言的读者对二进制位运算能有较好的理解,先介绍有关位的知识以及计算机中数值的编码表示方法。

1.字节和位

前已讲述,内存是以字节为单位的连续的存储空间,每个内存单元(字节(byte))有一个唯一的编号,即地址。

一个字节由8个二进制位(bit)组成,其中最右边的一位称为“最低位”,最左边的一位称为“最高位”。每一个二进制位的值是0或1。

2.数值的编码表示

在计算机内表示数值的时候,以最高位作为符号位,最高位为0表示数值为正,为1表示数值为负。表示数值,可采用不同的编码方法,一般有:原码、反码和补码。

(1)原码

用最高位作为符号位来表示数的符号:为0代表正数,为1代表负数,其余各位代表数值本身的绝对值(以二进制表示)。

例如:

+10的原码是:00001010

img115

为简化起见,假如用一个字节(八个二进位)表示整数。如果用两个字节存放一个整数,情况是一样的,只是把+10表示成00000000 00001010而已。

+0的原码是:00000000

−0的原码是:10000000

显然,+0和−0表示的是同一个数0,而在内存中却有两个不同的表示。由于0的表示方法不唯一,不适合计算机的运算,所以在计算机内部一般不使用原码来表示数。

(2)反码

正数的反码与原码相同,如+10的反码也是00001010。

而负数的反码是:原码除符号位外(仍为1),各位取反。如−10的反码是11110101。

+0的反码是:00000000

−0的反码是:11111111

同样,0的表示不唯一。所以在计算机内部一般也不使用反码来表示数。

(3)补码

正数的补码与原码相同。如+10的补码同样是00001010。而负数的补码是:除最高位仍为1外,原码的其余各位求反,最后再加1。例如,−10的原码是:10001010,求反(除最高位外)后,得到11110101,再加1,结果是11110110。或者说,负数的补码是其反码加1。

+0的补码是:00000000

−0的补码是:11111111

img116

所以,用补码形式表示数值0时,是唯一的,都是00000000。

现在计算机通常都是以补码形式存放数。因为采用补码形式不仅数值表示唯一,而且能将符号位与其他位统一处理。实际上采用补码,在计算机中可以使减法变为加法,为硬件实现提供方便。

3.位逻辑运算符与位逻辑表达式

位逻辑运算符有4种:

&(按位与);∣(按位或);~(按位取反);^(按位异或)。

由于它们都是按二进制位逐位地进行运算,相邻位之间不发生联系,即没有“进位”、“借位”等问题,所以称为位逻辑运算符。对参加逻辑运算的操作数,编译者是取其二进制的表达式进行的。

其中,除按位取反~是单目运算符外,其余3个是双目运算符。

位逻辑运算符的作用如表2.4.2所示。

表2.4.2 位逻辑运算符的作用

img117

(1)“按位与”运算符(&)

按位与的运算规则是:如果两个相应的二进制位都为1,则该位的结果为1,否则为0。即:

1 &1= 1,1 &0= 0,0 &1= 0, 0 &0= 0

例如:对下面的两个数进行按位与运算。

unsigned int i=4988,j=63286;

i为:

0001001101111100(即0x137C或011574)

j为:

1111011100110110 (即0xF736或0173466)则i&j为:

img118

&运算经常用于把特定位清零(屏蔽)。例如i的值为10100110,j的值为11100000,则i&j的结果是10100000,相当于把i的低5位屏蔽,高3位不变。可见,若要把某数的某些二进制位取出来,可以把其他位清零,把需要取出来的位同1做按位与即可。

注意:如果两个长度不同的数据(例如long型和int型)进行位运算时(如i&j,i为long型,j为int型),系统会将二者按右端对齐。如果j为正数,则左侧16位补满0;如果j为负数,则左侧16位补满1;如果j为无符号整型数,则左侧16位也补满0。

(2)“按位或”运算符(|)

按位或的运算规则是:两个相应的二进制位只要有一个为1,则该位的结果为1,否则为0。即:

1∣1= 1, 0∣1= 1, 1∣0= 1, 0∣0= 0

以上面的例子为例,i|j的结果为:

img119

按位或|运算经常用于把一个数据的某些位定值为1。例如要想使一个数m的低4位改为1,只需将m与017进行按位或即可。

(3)“按位异或”运算符(^)

按位异或的运算规则是:如果参与运算的两个相应的二进制位相同,则该位的结果为0,否则为1。即:

1^1=0,0^0=0,1^0=1,0^1=1

仍以上面的例子为例,i^j的结果为:

按位异或^运算符能使特定位按位变反,方法是将这些特定位与1异或。例如i的值为10100110,j的值为11100000,则i^j的结果是01000110。凡是与1异或的位都变反了,而与0异或的位不变。

(4)“按位取反”运算符(~)

用来对一个二进制数按位取反,即将0变为1,1变为0。即:

~1=0,~0=1

注意:对于按位取反(~)来说,~0x7 (即~07或~7)在16位机上就是:

1111111111111000  (即0xFFF8或0177770)

而在32位机上却是:

11111111111111111111111111111000(即0xFFFFFFF8或037777777770)

所以,在C程序中,最好采用~0x7或~07来表示7的逻辑取反,而不要采用形如

  0xFFF8、0177770或0xFFFFFFF8、037777777770

等表达式。主要原因是:前一种表达式与机器硬件特性无关,从而保证了程序的可移植性。

各个位逻辑运算符的优先级关系是:~最高,其余3个运算符的优先级从高到低依次是&、^、|,但三者都高于逻辑运算符而低于关系运算符。它们容易混淆,所以使用时注意加括号。例如:

  n =((i&j)|k)

由位逻辑运算符和运算分量构成的表达式称做位逻辑表达式。位逻辑表达式中运算分量都应该是整型量或字符型量,不允许是浮点型量。

位逻辑运算符与逻辑运算符之间的区别:

①位逻辑运算符是针对二进制位的,而逻辑运算符是针对整个表达式的;位逻辑运算符要计算表达式的具体数值,而逻辑运算符只判断表达式的真与假。

②位逻辑运算符&、|和 ^的两个运算分量是可交换的;而逻辑运算符&&和||的两个运算分量是不可交换的,并且它们严格执行自左至右的运算。例如:

  40&8 结果是8   40&&8 结果是1(真)

  40|8 结果是40  40||8 结果是1(真)

  0||x 结果是1(若x≠0) 或0(若x= 0)

  0&&x 结果是0,其中x是任意表达式

位逻辑运算符通常用于与硬件相应的程序中,如设备驱动程序,对表示状态字中的某些位进行测试、设置和屏蔽等。

4.移位运算符和移位表达式

C语言中实现移位功能的运算符有两个:“〈〈”(左移)和“〉〉”(右移)。

它们都是双目运算符,并且要求两个运算分量都是整型量。由移位运算符和运算分量构成的表达式称为移位表达式。

(1)左移位运算符〈〈

它的一般使用形式是:

  表达式1〈〈表达式2

其中,“表达式1”是移位对象,“表达式2”是表示移位的位数。它的功能是:把表达式1的值(以二进制形式表示)向左移动n位,n值由表达式2确定(该值必须是正整数)。

例如,m=00001011,那么,移位表达式

  m=m〈〈3

的结果是01011000,即把m的各二进制位全部向左移3位,右边空出的位补0,而左边溢出的位被丢弃不管。

在容许的范围内,利用左移位运算可扩大原数的倍数,左移1位扩大2倍,左移2位扩大4倍,即可实现被移对象乘以n2功能。例如,上面m的值是11,左移3位后,结果值是88,恰好等于11×2³ =11×8=88。

(2)右移运算符〉〉

它的一般使用形式是:

  表达式1〉〉表达式2

其中,“表达式1”是移位对象,“表达式2”是表示移位的位数。它的功能是:把表达式1的值(以二进制形式表示)向右移n位,n的值由表达式2确定(该值必须是正整数)。

例如,m=00001011,那么,移位表达式

  m= m〉〉2

的结果是00000010,即:把m的各二进制位全都向右移2位,右边溢出的位被丢弃,而左边空出的位(在本例情况下)补0。

右移一位相当于该数除以2,右移n位相当于该数除以n2。

在右移时,要注意符号位问题。如果移位对象是无符号数,那么右移时左边空出来的位全以0填充,这种方式称为逻辑右移方式;如果移位对象是有符号数,当移位对象是正数(符号位为0)时,左边空位用0填充;当移位对象是负数(符号位为1)时,左边空位是补0还是补1,要取决于所用的计算机系统。有的系统按逻辑右移方式(即补0)处理,有的系统则按算术右移方式(即补1)处理。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈