我們知道,程式中的所有資料在計算機記憶體中都是以二進位制的形式進行儲存的,資料的位是可以操作的最小資料單位,位元運算就是直接對整數在記憶體中的二進位制位進行操作。因此,在理論上,我們可以通過“位運算”來完成所有的運算和操作,從而有效地提高程式執行的效率。
C 語言中提供了 &(與)、|(或)、^(互斥或)、~(取反)、>>(右移)、<<(左移)6 種位元運算符。我們可以在程式中合理地使用這些位元運算符號來提高程式的執行效率,例如,對於下面的範例程式碼:
int x=0;
int y=0;
x = 257 /8;
y = 456 % 32;
我們可以通過位元運算符將其修改成如下形式:
int x=0;
int y=0;
x = 257 >>3;
y = 456 - (456 >> 4 << 4);
這樣就可以使程式在效能上得到一定提升。
盡量避免對未知的有符號數執行位元運算
在 C 語言中,如果在未知的有符號數上執行位元運算,很可能會導致緩衝區溢位,從而在某些情況下導致攻擊者執行任意程式碼,同時,還可能會出現出乎意料的行為或編譯器定義的行為。
下面來看一個簡單的範例:
#include <stdio.h>
int main (void)
{
int x=0;
int y=0x80000000;
char buf[sizeof("128")];
x=sprintf(buf,"%u",y>>24);
if(x==-1||x>=sizeof(buf))
{
// 錯誤處理
}
printf(buf);
return 0;
}
程式碼中,y>>24 的執行結果為 4294967168,而 sizeof(buf) 的結果為 4。當我們將 y>>24 的結果值轉換為字串“4294967168”時,超出了 buf 範圍,所以結果值無法完全儲存在 buf 中。因此,在執行語句“x=sprintf(buf,"%u",y>>24)”時,sprintf 方法在進行寫操作時就會越過 buf 的邊界,從而產生緩衝區溢位。
如果在編譯器 VC++ 中執行這段程式,將會產生如圖 1 所示的錯誤報告。
圖 1