C 語言中的位運算符
在 C 語言中,相同的數(shù)字可以用不同的數(shù)制來表示。也就是十進(jìn)制的數(shù)字可以等價的表示為二進(jìn)制或者十六進(jìn)制。那么對于二進(jìn)制來說,可以進(jìn)行逐個數(shù)字之間,也就是每一個數(shù)字位的運算。這種運算也廣泛的存在我們?nèi)粘淌褂玫臄?shù)字電路中。其實計算機(jī)的運算原理最底層就是位運算,也就是 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 |
對于非操作符有下表的結(jié)果。
x | ~x |
---|---|
0 | 1 |
1 | 0 |
移位操作就是將位向左或者向右移動,空位用 0 來補(bǔ)齊。
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;
}
運行結(jié)果如下:
x & y = 10
x | y = 15
x ^ y = 5
~ x = -11
~ y = -16
x << 2 = 40
x >> 2 = 3
那么我們分析一下這些結(jié)果。
10 = 1 0 1 0
15 = 1 1 1 1
10 & 15 = 1 0 1 0
按照上節(jié)的表格計算后,發(fā)現(xiàn) 10 與 15 進(jìn)行位與計算后,結(jié)果為 10 。
10 = 1 0 1 0
15 = 1 1 1 1
10 | 15 = 1 1 1 1
按照上節(jié)的表格計算后,發(fā)現(xiàn) 10 與 15 進(jìn)行位或計算后,結(jié)果為 15 。
10 = 1 0 1 0
15 = 1 1 1 1
10 ^ 15 = 0 1 0 1
按照上節(jié)的表格計算后,發(fā)現(xiàn) 10 與 15 進(jìn)行位異或計算后,結(jié)果為 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
因為一個整數(shù)是由 4 個字節(jié)組成,每個字節(jié)是 8 位,因此
在 1010 前還有 28 個 0 存在。將這些 0 全部變?yōu)?1 ,這時的數(shù)字代表 -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 全部變?yōu)?1 ,這時的數(shù)字代表 -40。
10 = 1 0 1 0
10 << 2 = 1 0 1 0 0 0
把 10 向左移動兩位,右面的空余位置用 0 補(bǔ)齊。
Tips:請?zhí)貏e注意,在向左移位的過程中,如果左移的位數(shù)超出數(shù)據(jù)的存儲最大位數(shù),那么將產(chǎn)生錯誤。
下面的示例程序展示了這種錯誤。
# 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 類型可以表示的最大位數(shù)。
在編譯的時候,會出現(xiàn)如下的錯誤。
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 補(bǔ)齊。
3. 小結(jié)
位運算作為一種直接的,符合數(shù)字電路邏輯的運算,廣泛的存在于我們的生活中。在編程語言中,通過位運算可以方便的獲得如網(wǎng)絡(luò)地址的計算,還有我們?nèi)粘5囊恍┘訙p乘除都是可以通過位運算來實現(xiàn)的。只不過很多運算由于表示不直觀,容易出錯,所以還是使用了普通的算數(shù)運算符等來進(jìn)行計算。
同時也要區(qū)分,位運算與我們介紹的邏輯運算符很相似,所以請大家注意區(qū)分。