4月从零学习C语言(第27天)——位运算符
位运算
我们知道计算机程序中的所有数在计算机内存中都是以二进制的形式来储存的。而直接对整数在内存中的二进制位进行操作的运算就是位运算。在C语言中也给我们提供了位运算。
位运算符
C语言为我们提供了6中位运算符:
运算符 | 名称 | 描述 |
---|---|---|
& | 按位与 | 让参与运算的两个数对应的二进制位分别相与 |
| | 按位或 | 让参与运算的两个数对应的二进制位分别相或 |
^ | 按位异或 | 让参与运算的两个数对应的二进制位分别相异或 |
~ | 按位反 | 把运算对象的内容按位取反 |
<< | 左移 | 把<< 左边的运算数的各位二进制位全部左移若干位 |
>> | 右移 | 把>> 左边的运算数的各位二进制位全部右移若干位 |
在以上运算中除了~
为单目运算外,其余均为双目运算符。另外运算对象只能是整型或者字符型数据,不能是实型数据。
拓展:&、 | 和 ^ 的真值表如下所示:
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
按位与
让参与运算的两个数对应的二进制位分别相与。只有对应的两个位均为1时,结果才为1,否则为0.即0&0=0,0&1=0,1&0=0,1&1=1。
例如9&5:
00001001 //9的二进制原码
&00000101 //5的二进制原码
——————————
00000001 //1的二进制原码
实例:
#include <stdio.h>
int main()
{
int a=9,b=5,c;
c=a&b;
printf("%d&%d=%d \n",a,b,c);
return 0;
}
运行结果:
按位或
让参与运算的两个数对应的二进制位分别相与。只有对应的两个二进制位均有一个1时,结果就为1,否则为0.即0|0=0,0|1=1,1|0=1,1|1=1。
例如6|2:
00000110 //6的二进制原码
|00000010 //2的二进制原码
——————————
00000110 //2的二进制原码
实例:
#include <stdio.h>
int main()
{
int a=6,b=2,c;
c=a|b;
printf("%d|%d=%d \n",a,b,c);
return 0;
}
运行结果:
按位异或
让参与运算的两个数对应的二进制位分别相异或。只有对应的两个二进制位不同时,结果就为1,否则为0.即00=0,01=1,10=1,11=0。
例如6^2:
00000110 //6的二进制原码
^00000010 //2的二进制原码
——————————
00000100 //4的二进制原码
按位异或的几个常见用途:
(1) 使某些特定的位翻转
例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。
10100001^00000110 = 10100111
(2) 实现两个值的交换,而不必使用临时变量。
例如交换两个整数a=10100001,b=00000110的值,可通过下列语句实现:
a = a^b; //a=10100111
b = b^a; //b=10100001
a = a^b; //a=00000110
(3) 与0按位异或,保留原值。
按位取反
按位取反运算符为单目运算符,运算对象就至于运算符的右边,具有右结核性。功能就是把运算符的内容取反,即0变成1,1变成0.
例如~9:
~(00001001)
结果为:11110110
左移
二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
例如:
int a=8,b;
b=a<<3;
在二进制表示运算过程如下:
a: 00001000(a=8)
b=<<3: 01000000(b=64)
右移
二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
例如:
int a=15,b;
b=a>>2;
在二进制表示运算过程如下:
a: 00001111(a=8)
b=>>2: 00000011(b=64)