C语言的语法基础

2.3.4位运算

 

数据在内存中都以二进制形式存放,如果对硬件编程,或作系统调用经常需要对数据的二进制位进行操作。通常高级语言不提供位运算符,但C语言提供了位运算符,与汇编语言的位操作相似,是C语言的优点之一。

    1.位运算符

C语言提供了六种位运算符,其优先级、结合方向、要求运算对象的个数及作用如表2.16所示。

表2.16   C语言的位运算符 

操作符

优先级

作用

要求运算对象的个数

结合方向

  高

   低

按位取反

1(单目)

从右到左

<<,>>

左移,右移

2(双目)

从左到右

&

按位与

2(双目)

从左到右

按位异或

2(双目)

从左到右

|

按位或

2(双目)

从左到右

位运算的运算对象只适用于字符型和整数型数据,对其它数据类型不适用。关系表达式和逻辑表达式的值只能是1或0,而位运算表达式的值可以是0或1以外的值。

  2.位运算符的运算规则

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

按位取反运算符是单目运算符,运算对象在运算符的右边,其运算功能是把运算对象的内容按位取反。例如:int i=199;则~i值为-200,这是因为:

整型十进制数199的二进制数是:

0000 0000 1100 0111

把它按位取反 1111 1111 0011 1000  这个数是整型十进制数-200在内存的补码表示。

(2)左移运算符“<<”

左移运算符的左边是运算对象,右边是整型表达式,表示左移的位数。

左移时,低位(右端)补0,高位(左端)移出部分舍弃。例如:

char a=5,b;

b=a<<3;

用二进制来表示,  a的值为   0000 0101 (十进制数5)

执行语句b=a<<3;之后,b的值为  0010 1000 (十进制数40=5*2*2*2),运算后a的值并没有改变仍为5)。左移时,若高位(左端)移出的部分均是二进制位数0,则每左移1位,相当于乘以2。可以利用左移这一特点,代替乘法,左移运算比乘法运算快得多。若高位移出的部分包含有二进制位数1,则不能用左移代替乘法运算。

(3)右移运算符“>>”

右移运算符的左边是运算对象,右边是整型表达式,表示右移的位数。

右移时,低位(右端)移出的二进制位数舍弃。对于正整数和无符号整数,高位(左端)补0;对于负数,高位(左端)补1(补码表示法最高位1表示负数)。例如:

char a=41,b;

b=a>>3;

用二进制来表示,           a的值为   0010 1001 (十进制数41)

执行语句b=a>>3;之后,  b 的值为         0000 0101 (十进制数5=41/2/2/2,注意是整数除),运算后a的值并没有改变仍为41)。右移时,每右移1位,相当于除以2(整数除)。可以利用右移这一特点,代替除法,右移运算比除法运算快得多。但是对于负整数,右移时高位(左端)补1,则不能用右移代替除法运算。

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

运算符“&” 先把两个运算对象按位对齐,再进行按位与运算,如果两个对应的位都为1,则该位的运算结果为1,否则为0。例如:int a=41&165 ;则a的值为33,运算过程用二进制表示如下,

0000 0000 0010 1001   (十进制数41)

& 0000 0000 1010 0101   (十进制数165)

0000 0000 0010 0001    (十进制数33)

按位与运算有两个特点:和二进制位数0相与则该位被清零;和二进制位数1相与则该位保留原值不变。利用这两个特点,可以指定一个数的某一位(或某几位)置0,也可以检验一个数的某一位(或某几位)是否是1。例如:a=a&3;只保留a的右端两位二进制位数。

又如:a & 4 检验变量a的右端第3位是否为1。

按位与运算符“&”和逻辑与运算符“&&”不同,对于逻辑与运算符“&&”,只要两边运算数为非0,运算结果为1。例如 41&&165 的值是1。

(5)按位异或运算符“∧”

按位异或运算符“∧”把两个运算对象按位对齐,如果对应位上的数相同,则该位的运算结果为0;如果对应位上的数不相同,运算结果为1。例如:int a=41∧165 ;则a的值为140,运算过程用二进制表示如下,

0000 0000 0010 1001   (十进制数41)

∧ 0000 0000 1010 0101   (十进制数165)

0000 0000 1000 1100    (十进制数140,运算时上、下相同取0,不同取1)

按位异或运算可以把一个数的二进制位的某一位(或某几位)翻转(0变1,1变0)。例如:a=a∧3;将变量a的最右端的二位翻转。

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

按位或运算符“|”先把两个运算对象按位对齐,再进行按位或运算,如果两个对应的位都为0,则该位的运算结果为0,否则为1。例如:int a=41|165 ;则a的值为173,运算过程用二进制表示如下,

0000 0000 0010 1001   (十进制数41)

| 0000 0000 1010 0101   (十进制数165)

0000 0000 1010 1101    (十进制数173)

利用按位或运算的特点,可以指定一个数的某一位(或某几位)置1,其它位保留原值不变。例如:a=a|3;把a的右端两位二进制位数置1, 其它位保留原值不变。

a=a|0xff;  把a的低字节全置1,高字节保持原样。

a=a|0xff00; 把a的高字节全置1,低字节保持原样。

(7)不同数据类型之间的位运算

如果参加位运算的两个运算对象类型不同,例如长整型(long)、整型(int)或字符型(char)数据之间的位运算。此时先将两个运算对象右端对齐,若为正数或无符号数高位补0 ,负数高位补1。

例如:9L|-200的值为  ,运算过程用二进制表示如下:

0000 0000 0000 0000 0000 0000 0000 1001 (十进制长整型数9L)

|  1111 1111 1111 1111 1111 1111 0011 1000 (十进制数-200,高位补1)

1111 1111 1111 1111 1111 1111 0011 1001  (十进制长整型数-199L)

(8)一个表达式中出现多个位运算符

如果在一个表达式中出现多个运算符时,应注意各运算符之间的优先关系。例如:

语句a=10&5<<3;执行后a的值为8。“<<”的优先级高于“&”,先进行位移运算。

Tags:

发表评论