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; // 10 = 1010
y=15; // 15 = 1111
z=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<<2;
printf("x << 2 = %d\n", z);
z=y>>2;
printf("x >> 2 = %d\n", z);
return 0;
}
運行結果如下:
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; // 10 = 1010
z=x<<200;
printf("x << 200 = %d\n", z);
return 0;
}
顯然超過了 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. 小結
位運算作為一種直接的,符合數字電路邏輯的運算,廣泛的存在于我們的生活中。在編程語言中,通過位運算可以方便的獲得如網絡地址的計算,還有我們日常的一些加減乘除都是可以通過位運算來實現的。只不過很多運算由于表示不直觀,容易出錯,所以還是使用了普通的算數運算符等來進行計算。
同時也要區分,位運算與我們介紹的邏輯運算符很相似,所以請大家注意區分。