C語言詳細(xì)講解位運算符的使用
一、位運算符分析
C語言中的位運算符
位運算符直接對 bit 位進行操作,其效率最高。
| & | 按位與 |
| | | 按位或 |
| ^ | 按位異或 |
| ~ | 取反 |
| << | 左移 |
| >> | 右移 |
左移和右移注意點
左操作數(shù)必須為整數(shù)類型
- char 和 short 被隱式轉(zhuǎn)換為 int 后進行移位操作
右操作數(shù)的范圍必須為:[0,31]
左移運算符<< 將運算數(shù)的二進制位左移
- 規(guī)則:高位丟棄,低位補0
右移運算符>> 把運算數(shù)的二進制位右移
- 規(guī)則︰高位補符號位,低位丟棄
下面一段代碼:
#include <stdio.h>
int main()
{
printf("%d\n", 3 << 2);
printf("%d\n", 3 >> 1);
printf("%d\n", -1 >> 1);
printf("%d\n", 0x01 << 2 + 3);
printf("%d\n", 3 << -1); // oops!
return 0;
}下面為輸出結(jié)果:

注意四則運算優(yōu)先級大于位運算,所以 0x01 << 2 + 3 的結(jié)果是 32。 還有就是右操作數(shù)的范圍必須為:[0,31],如果不在這個范圍內(nèi),程序的輸出結(jié)果由不同類型的編譯器所決定,結(jié)果將不確定,就像本代碼 3 << -1 一樣。
二、小貼士
防錯準(zhǔn)則:
- 避免位運算符,邏輯運算符和數(shù)學(xué)運算符同時出現(xiàn)在一個表達式中
- 當(dāng)位運算符,邏輯運算符和數(shù)學(xué)運算符需要同時參與運算時,盡量使用括號 ( ) 來表達計算次序
小技巧:
- 左移 n 位相當(dāng)于乘以 2 的 n 次方,但效率比數(shù)學(xué)運算符高
- 右移 n 位相當(dāng)于除以 2 的 n 次方,但效率比數(shù)學(xué)運算符高
下面看一段交換兩個整型變量值的代碼:
#include <stdio.h>
#define SWAP1(a,b) \
{ \
int t = a; \
a = b; \
b = t; \
}
#define SWAP2(a,b) \
{ \
a = a + b; \
b = a - b; \
a = a - b; \
}
#define SWAP3(a,b) \
{ \
a = a ^ b; \
b = a ^ b; \
a = a ^ b; \
}
int main()
{
int a = 1;
int b = 2;
//printf("a = %d\n", a);
//printf("b = %d\n", b);
SWAP1(a,b);
printf("a = %d\n", a);
printf("b = %d\n\n", b);
a = 1;
b = 2;
SWAP2(a,b);
printf("a = %d\n", a);
printf("b = %d\n\n", b);
a = 1;
b = 2;
SWAP3(a,b);
printf("a = %d\n", a);
printf("b = %d\n\n", b);
return 0;
} 第一種方法需要引入第三方變量,第二種方法可能會導(dǎo)致越界問題,第三種的方法效率較高,且不用引入第三方變量。
注意第三種方法:執(zhí)行 a = a ^ b; 后,b = a ^ b; 就相當(dāng)于 b = a ^ b ^ b; 先計算后面的,就是 b = a ^ 0,結(jié)果就是 b = a;再執(zhí)行a = a ^ b;相當(dāng)于 a = a ^ b ^ b,即 a = a ^ b ^ a,顯然結(jié)果是 b。
小知識:
A 異或 0 等于 A ,A 異或 1 等于 非A。
三、位運算與邏輯運算
位運算與邏輯運算不同:
- 位運算沒有短路規(guī)則,每個操作數(shù)都參與運算
- 位運算的結(jié)果為整數(shù),而不是 0 或 1
- 位運算優(yōu)先級高于邏輯運算優(yōu)先級
下面再來看一個混淆改變的判斷條件:
#include <stdio.h>
int main()
{
int i = 0;
int j = 0;
int k = 0;
if( ++i | ++j & ++k )
{
printf("Run here...\n");
}
printf("i = %d, j = %d, k = %d\n\n", i, j, k);
i = 0;
j = 0;
k = 0;
if( ++i || ++j && ++k )
{
printf("Run here...\n");
}
printf("i = %d, j = %d, k = %d\n\n", i, j, k);
return 0;
}下面為輸出結(jié)果:

可以看到,如果錯把++i || ++j && ++k 寫成++i | ++j & ++k,雖然都能運行,但是其中的執(zhí)行細(xì)節(jié)不一樣,在實際工程中可能會出現(xiàn) bug,而且還不好排查。
四、小結(jié)
- 位運算符只能用于整數(shù)類型
- 左移和右移運算符的右操作數(shù)范圍必須為 [0,31]
- 位運算沒有短路規(guī)則,所有操作數(shù)均會求值
- 位運算的效率高于四則運算和邏輯運算
- 運算優(yōu)先級:四則運算 > 位運算 > 邏輯運算
到此這篇關(guān)于C語言詳細(xì)講解位運算符的使用的文章就介紹到這了,更多相關(guān)C語言 位運算符內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ vector如何動態(tài)申請內(nèi)存的元素
vector是一種動態(tài)數(shù)組,本文主要介紹了C++ vector如何動態(tài)申請內(nèi)存的元素,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07
Linux環(huán)境下段錯誤的產(chǎn)生原因及調(diào)試方法小結(jié)
借此機會系統(tǒng)學(xué)習(xí)了一下,這里對Linux環(huán)境下的段錯誤做個小結(jié),方便以后同類問題的排查與解決2011-11-11

