|
C语言有一个重要特点就是可以直接对二进制位进行操作,即位运算。
二进制位简称位(bit),其值为0或1。计算机真正执行的正是由0和1构成的机器指令,计算机内数据也是由二进制表示的。
数在计算机内均是以补码的形式存储的 。
1 位运算符

2 位运算
2.1 按位取反运算
取反运算“~”是一个单目运算符,运算量在运算符之后,取反运算的功能是将一个数据中所有位都取其相反值,即1变0,0变1。
运算规则为: ~1=0 ~0=1
例1 对于无符号的字符型数据
a=(18)10 =(00010010)2 ,
则~a等于(11101101)2 ,即(237)10
C程序如下:
# include <stdio.h>
int main()
{
unsigned char a=18,b;
b=~a;
printf(“~a=%d”,b);
return 0;
}运行结果为: ~a= 237
注意以下程序与上面程序及运行结果的区别:
#include <stdio.h>
int main()
{
char a=18,b; b=~a;
printf(“~a=%d”,b);
return 0;
}运行结果:-19
注意:
前一个程序结果很好理解,后一个因为a是带符号数据,因此~a=(11101101)2的结果是一负数的补码,转换为原码时,第1位符号位不变,对剩余的部分先减1,再全部取反,因此得到的二进制原码为:10010011,即十进制的-19。
2.2 左移运算
左移运算“<<”是一个双目运算符,左移运算的功能是将一个数据所有位向左移若干位,左边(高位)移出的部分舍去,右边(低位)自动补零。
例2 对于无符号字符型数据
a=(18)10 =(00010010)2 ,
a <<3的结果是(10010000)2 ,即(144)10
C程序如下:
#include <stdio.h>
int main()
{
unsigned char a=18, b;
b=a<<3;
printf(“a<<3=%d”,b);
}运行结果为: a<<3=144
注意以下程序与上面程序的区别:
# include <stdio.h>
int main()
{
char a=18,b;
b=a<<3;
printf(“a<<3=%d”,b);
return 0;
} 运行结果为: a<<3=-112
原因同前,对于带符号数a,因a<<3得到的(10010000)2, 是一负数的补码,转换为原码时,第1位符号位不变,对剩余的部分先减1,再全部取反,因此得到的二进制原码为:11110000,即十进制的-112。
对于无符号数来说,在左移的过程中如果没有高位的丢失,左移1位相当于乘2,左移2位相当于乘4。
左移运算速度较快,因此有些C编译系统自动将乘2的操作用左移1位来实现,将2的n次幂运算用左移n位来实现。
2.3 右移运算
右移运算“>>”是一个双目运算符,右移运算的功能是将一个数据所有位向右移若干位,右边(低位)移出的部分舍去,左边(高位)移入的二进制数分两种情况:对于无符号数和正整数,高位补0;对于负整数,高位补1(适用于turboc系统)。
例3 对于无符号字符型数据
a=(18)10 =(00010010)2 ,
则 a >>3的结果是(00000010)2,即(2)10
C程序:
# include <stdio.h>
int main()
{
unsigned char a=18, b;
b=a>>3;
printf(“a>>3=%d”,b);
return 0;
}运行结果为: a>>3=2
2.4 按位与运算
按位“与”运算符要求有两个运算量,其功能是将两个运算量的各个相应位分别进行“与”运算。
运算规则为: 1&1=1 0&1=0 1&0=0 0&0=0
例4 对于无符号数a=(173)10=(10101101)2,
b=(203)10=(11001011)2,
则a&b = (10001001)2 =(137)10

C程序:
# include <stdio.h>
int main()
{
unsigned char a=173,b=203,c;
c=a&b;
printf(“a&b=%d”,c);
return 0;
}运行结果为: a&b=137
C程序:
# include <stdio.h>
int main()
{ char a=-83,b=-53,c;
c=a&b;
printf(“a&b=%d”,c);
return 0;
}运行结果为: a&b=-119
例5 对于有符号数a=(-83)10=(10101101)2 ,
b=(-53)10=(11001011)2 ,
则a&b = (10001001)2 =(-119)10 。
以上二进制形式是负数的补码。C程序如下所示。

2.5 按位或运算
按位“或”运算符要求有两个运算量,其功能是将两个运算量的各个相应位分别进行“或”运算。
运算规则为: 1|1=1 0|1=1 1|0=1 0&0=0
例6 对于无符号数a=(173)10=(10101101)2,b=(203)10=(11001011)2,则a|b = (11101111)2 =(239)10

C程序:
# include <stdio.h>
int main()
{
unsigned char a=173,b=203,c;
c=a|b;
printf(“a|b=%d”,c);
return 0;
}
运行结果: a|b=239 例7 对于有符号数
a=(-83)10=(10101101)2,
b=(-53)10=(11001011)2,
则a|b = (11101111)2 =(-17)10

C程序:
# include <stdio.h>
int main()
{
char a=-83,b=-53,c;
c=a|b;
printf(“a|b=%d”,c);
return 0;
}运行结果为: a|b= -17
2.6 按位异或运算
按位“异或”运算符要求有两个运算量,其功能是将两个运算量的各个相应位分别进行“异或”运算。
运算规则为: 1^1=0 0^1=1 1^0=1 0&0=0 。
例8 对于无符号数
a=(173)10=(10101101)2,
b=(203)10=(11001011)2,
则a^b = (11101111)2 =(102)10
C程序:
# include <stdio.h>
int main()
{
unsigned char a=173,b=203,c;
c=a^b; printf(“a^b=%d”,c);
return 0;
} 运行结果: a^b=102
 |
|