C 语言位运算符
在 C 语言中,相同的数字可以用不同的数制来表示。也就是十进制的数字可以等价的表示为二进制或者十六进制。那么对于二进制来说,可以进行逐个数字之间,也就是每一个数字位的运算。这种运算也广泛的存在我们日程使用的数字电路中。其实计算机的运算原理最底层就是位运算,也就是 0 和 1 的运算。
1. 位运算符
运算符 | 作用 | 示例 |
---|---|---|
& | 位与 | a&b |
| | 位或 | a|b |
^ | 位异或 | a^b |
~ | 位非 | ~b |
<< | 位左移 | a<<b |
>> | 位右移 | a>>b |
对于位运算中的与、或、异或可以通过下面的表格来阐明。
x | y | x & y | x | y | x ^ y |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
对于非操作符有下表的结果。
x | ~x |
---|---|
0 | 1 |
1 | 0 |
移位操作就是将位向左或者向右移动,空位用 0 来补齐。
2. 示例
# include <stdio.h>int main(){int x,y,z;x=; // 10 = 1010y=; // 15 = 1111z=x&y;printf("x & y = %d\n", z);z=x|y;printf("x | y = %d\n", z);z=x^y;printf("x ^ y = %d\n", z);z=~x;printf("~ x = %d\n", z);z=~y;printf("~ y = %d\n", z);z=x<<;printf("x << 2 = %d\n", z);z=y>>;printf("x >> 2 = %d\n", z);return ;}
运行结果如下:
x & y = 10 x | y = 15 x ^ y = 5 ~ x = -11 ~ y = -16 x << 2 = 40 x >> 2 = 3
那么我们分析一下这些结果。
10 = 1 0 1 0 15 = 1 1 1 1 10 & 15 = 1 0 1 0
按照上节的表格计算后,发现 10 与 15 进行位与计算后,结果为 10 。
10 = 1 0 1 0 15 = 1 1 1 1 10 | 15 = 1 1 1 1
按照上节的表格计算后,发现 10 与 15 进行位或计算后,结果为 15 。
10 = 1 0 1 0 15 = 1 1 1 1 10 ^ 15 = 0 1 0 1
按照上节的表格计算后,发现 10 与 15 进行位异或计算后,结果为 5 。
10 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 ~ 10 = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1
因为一个整数是由 4 个字节组成,每个字节是 8 位,因此
在 1010 前还有 28 个 0 存在。将这些 0 全部变为 1 ,这时的数字代表 -11。
15 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 ~ 15 = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
在 1111 前还有 28 个 0 存在。将这些 0 全部变为 1 ,这时的数字代表 -40。
10 = 1 0 1 0 10 << 2 = 1 0 1 0 0 0
把 10 向左移动两位,右面的空余位置用 0 补齐。
Tips:请特别注意,在向左移位的过程中,如果左移的位数超出数据的存储最大位数,那么将产生错误。
下面的示例程序展示了这种错误。
# include <stdio.h>int main(){int x,y,z;x=; // 10 = 1010z=x<<;printf("x << 200 = %d\n", z);return ;}
显然超过了 int 类型可以表示的最大位数。
在编译的时候,会出现如下的错误。
test.c: In function ‘main’: test.c:7:8: warning: left shift count >= width of type [-Wshift-count-overflow] z=x<<200;
15 = 1 1 1 1 15 >> 2 = 0 0 1 1
把 15 向右移动两位,左面的空位用 0 补齐。
3. 小结
位运算作为一种直接的,符合数字电路逻辑的运算,广泛的存在于我们的生活中。在编程语言中,通过位运算可以方便的获得如网络地址的计算,还有我们日常的一些加减乘除都是可以通过位运算来实现的。只不过很多运算由于表示不直观,容易出错,所以还是使用了普通的算数运算符等来进行计算。
同时也要区分,位运算与我们介绍的逻辑运算符很相似,所以请大家注意区分。