C 语言位运算符

C 语言位运算符

在 C 语言中,相同的数字可以用不同的数制来表示。也就是十进制的数字可以等价的表示为二进制或者十六进制。那么对于二进制来说,可以进行逐个数字之间,也就是每一个数字位的运算。这种运算也广泛的存在我们日程使用的数字电路中。其实计算机的运算原理最底层就是位运算,也就是 0 和 1 的运算。

1. 位运算符

运算符作用示例
&位与a&b
|位或a|b
^位异或a^b
~位非~b
<<位左移a<<b
>>位右移a>>b

对于位运算中的与、或、异或可以通过下面的表格来阐明。

xyx & yx | yx ^ y
00000
01011
10011
11110

对于非操作符有下表的结果。

x~x
01
10

移位操作就是将位向左或者向右移动,空位用 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. 小结

位运算作为一种直接的,符合数字电路逻辑的运算,广泛的存在于我们的生活中。在编程语言中,通过位运算可以方便的获得如网络地址的计算,还有我们日常的一些加减乘除都是可以通过位运算来实现的。只不过很多运算由于表示不直观,容易出错,所以还是使用了普通的算数运算符等来进行计算。

同时也要区分,位运算与我们介绍的逻辑运算符很相似,所以请大家注意区分。