2011-09-19 58 views
3

我用下面的宏在C:關於產品使用C test_bit宏觀

#define test_bit(_n,_p)  !! (_n & (1u << _p)) 

我研究宏觀,但我需要確定在宏中使用雙重否定的,以及它如何從宏定義的行爲有所不同:

#define test_bit(_n,_p)  (_n & (1u << _p)) 

回答

2

它將不同的表現,如果你鏈一些算術或位運算符的宏。例如,如果你有

#define test_bit(_n,_p)  (_n & (1u << _p)) 

test_bit(whatever, 1) | test_bit(whatever, 4) 

結果會有所不同,你必須與

#define test_bit(_n,_p)  !! (_n & (1u << _p)) 

而且否定之否定就是another way of writing != 0之一。

2

基本上,雙重否定的目的是約束由宏返回到0和1值。在

if(test_bit(x, 5)) x=0; // (1) 
array[test_bit(x, 5)] = 0; // (2) 

在(1),這兩個定義的等效工作。在(2)中,第一個定義總是設置array[0]array[1],而第二個定義不是。

10

想想當你測試的特定位會發生什麼:

1111 1111 (0xff) 
& 0000 0100 (0x04, bit 2) 
    ---- ---- 
= 0000 0100 (0x04) 

如果你離開它這樣,你的結果將是位掩碼本身。

現在考慮的是,雙重否定,這是一樣無所作爲:

!4 -> 0 
!0 -> 1 

換句話說,!!4給你1而不是4,這保證你會得到一個0/1真值而不是0/whatever-the-bitmask-was值。


以下程序顯示了這個動作:

#include <stdio.h> 

#define test_bit0(_n,_p) (_n & (1u << _p)) 
#define test_bit1(_n,_p) !!(_n & (1u << _p)) 

int main (void) { 
    printf ("%d %d\n", test_bit0 (0xff, 2), test_bit1 (0xff,2)); 
    return 0; 
} 

並輸出:

4 1 

如預期。

旁白:有珍貴稀少的地方,你會寫代碼一樣,時下,因爲現代編譯比達的內聯代碼自動任務,並選擇最有效的方式做到像((_n & (1u << _p)) != 0)的操作了。不要讓我開始對使用鈍變量名,使用numberposition提供更在於它在編譯的時候失去了:-)

+0

可讀性您還可以提及的是,C99類型轉換爲' bool'類型基本上和'!!'opertor一樣。 –