2011-11-11 53 views
5

根據PC - 皮棉,下面的語句將永遠TRUE此C/C++ if()語句是否可以計算爲TRUE?

if((variable & 0x02) == 1) 

我使用的用於嵌入式系統的C編譯器,評估它TRUE每當variable相應的位設置。我猜編譯器正在做==兩邊的比較,而不是比較結果的數字。換句話說,每當表達式(varable & 0x02)不是零(即TRUE)時,該語句也將是TRUE,因爲值1 is also TRUE(非零)。

我不知道C/C++標準是否明確定義了編譯器在這種情況下的行爲。是否有任何C/C++專家可以根據標準(如C90, C99,等)的說法回答此問題?

P.S .:在上面的語句中,「variable」是一個無符號的字符。

+4

什麼是'variable'的類型? –

+2

你能否給這個編譯器命名?我的一個朋友收集了一些奇怪的編譯器錯誤。 – blaze

+1

您的真實代碼是否有雙重&符號(例如「var && 0x02」)?這將解釋編譯器將其評估爲真實。 – tinman

回答

11

PC-lint是正確的。假設var是整數變量,表達式var & 0x02可以評估爲兩個值:02。它永遠不會等於1,這是if語句正在測試的內容。

爲了擴展這一點,等號運算符被應用於兩個整數值。重要的是兩個操作數是否都是相同的數字,而不是它們是同時「真」還是「假」。

爲了測試第1位是否被設置,可以使用:

if (variable & 0x02) { 
    ... 
} 

考慮到你的編譯器的行爲,你說這樣做,這顯然不符合標準的方式。但是,它幾乎肯定會正確處理if (variable & 0x02)。我的建議是修改代碼,以便在您更改編譯器時不會無聲無息地破解代碼。最後,如果出現以下情況,情況就會不同:(1)代碼是C++而不是C;和(2)variable是一個類的實例; (3)該類超負荷運營商。在這種情況下,行爲取決於重載操作員實際做的事情。

+0

這是因爲'0x02'只有一個位設置在其位模式。 –

+4

由於存在重載操作符,C++中不是這種情況。 – bdonlan

+2

理想情況下,如果要檢查是否設置了給定掩碼中的所有位,則應始終使用「if((variable&CONST)== CONST)」模式。 – tylerl

6

在C++中,如果(且僅當)variable是一個帶有重載的operator&的類的實例,則該值可以評估爲真值,該類不符合正常的按位與語義。

在C中,這種情況將永遠是錯誤的。 §6.5.10定義位AND運算符的語義,這是相當簡單的一點:

  4.二元&操作的結果是按位操作數AND(即每在 中,當且僅當轉換的操作數中的每個對應位都是 set)時纔會設置結果。

很明顯,結果無法1中,作爲1位未在右手側的操作數的轉換的值設置(即,0x02)。

當然,如果在程序過去的某個時間點(或者在編譯時!)調用了未定義的行爲,那麼任何事情都可能發生。除了這種可能性,然而,你的編譯器不符合標準。這就是說,破碎。不幸的是,這是奇怪的嵌入式編譯器上常見的極端。如果你幸運的話,你甚至可以報告bug並修復它。

4

我不認爲標準定義了有關這個非常特殊和不尋常的問題的任何內容。如AIX說,這句話永遠是正確的,因爲(二進制):

XXXX XXXX -> variable 
0000 0010 -> 0x02 
--------- AND 
0000 00X0 -> result 

(簡化爲8位類型)

所以你唯一的結果可能是0000 0010(這是2)或0000 0000(它是0)。

+1

感謝您的視覺表現:) – AntonioCS

0

基本上,lint就在這裏。至少在任何我知道的平臺上,這種情況都會產生錯誤。查看數字的位表示:對於任何整數x,(0010)將始終爲零或2(0010),因此與1(0001)不同。

1

對於C,答案是否定的。

C standard說,大約&(6.5.10):

二元&操作的結果是位與操作數(即,每個位 結果被設定,當且僅如果轉換的操作數中的每個對應位都是 set)。

由於2只有1位被設置,則表達式的值只能設置的位1。它可以採取任何其它的值大於2和0無論2還是0可以比較等於1。

整數的位表示在6.2.6.2中定義(對於通常方式的非負值)。

0

讓我們考慮的2

02 = 0010 (say a 4 bit number) 

二進制值和1的二進制值是

01 = 0001 

2的至少significat位總是零是最左邊的位爲0 。SO
&(和)操作0從未給出1因此我們可以說它不可能等於1

 0 0 => 0 
     0 1 => 0 
     1 1 => 1 

注:&表示逐位和操作

2 - 0010 
    3 - 0011 
     0010 

因此,與XX & 2的輸出將是0或2