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。“<<”的优先级高于“&”,先进行位移运算。
发表评论