2012-12-19 32 views
1
#include <stdio.h> 

int foo(int a, int b) 
{ 
     return ((a>>= b<<= a) ? 1 : 0); 
} 

void bar(int x, int y) 
{ 
     printf("%d,%d: %s\n",x, y, (foo(x,y) ? "Equal" : "Not Equal")); 
} 

int main() 
{ 
     bar(0,1); 
     bar(4,4); 
     bar(3,2); 
     bar(9,9); 
     bar(-2,-2); 
     bar(-8,8); 
     return 0; 
} 

上述程序的輸出是奇怪的平等檢查使用逐移位運算

0,1: Not Equal 
4,4: Equal 
3,2: Not Equal 
9,9: Equal 
-2,-2: Equal 
-8,8: Equal 

你能幫助我理解平等檢查在功能foo()是如何工作的?如果一個論點是積極的而另一個是否定的,爲什麼它失敗函數foo()中的解決方法是什麼,以正確顯示所有情況下的結果,即所有負面和正面參數的解決方法?

編輯:從下面的答案,對於其他值的結果是:

70,72: Equal 
-2,-2: Equal 
64,64: Equal 
128,32: Equal 
256,250: Not Equal 
250,256: Equal 
-250,-256: Equal 

請解釋一下,爲什麼這種平等檢查適用於某些值集,而不是爲別人。裏面發生了什麼?

回答

7

這不是相等性檢查(你可以清楚地從結果中看到的),這是一個任務:

a = (a >> (b = b << a)); //results in UB for negatives 

相等性檢查是簡單

a == b; 
+0

但是,如果它是明確的賦值,那麼'foo()'能夠正確輸出所有正輸入嗎? (上面問題的輸出示例) –

+0

@Manav巧合?無論如何,你爲什麼要這樣做?普通的老式'=='有什麼問題? –

+0

'foo()'似乎可以很好地處理單個數字的數字:) –

5

失敗的原因時,一個論點是積極的而另一個是否定的 函數foo()對所有情況正確顯示結果(即所有負面和正面參數)的解決方法是什麼?

答案在於在C99-標準(ISO C99:6.5.7按位的移位運算符):

/4。 E1 << E2的結果是E1左移E2位的位置;空位填充了 零。如果E1具有無符號類型,則結果的值爲E1 × 2E2,比模型 還原的結果的數量多一個結果類型中可表示的最大值。如果E1有一個有符號的 類型和非負值,並且E1 × 2E2可以在結果類型中表示,那麼就是 的結果值;否則,行爲是不確定的。

所以foo(-2,-2)未定義的行爲

/5。 E1 >> E2的結果是E1右移E2位的位置。如果E1具有無符號類型 或者E1具有帶符號類型和非負值,則結果的值是E1/2E2的商的整數 部分。如果E1具有帶符號的類型和負值,則結果值爲實施定義。

所以foo(-8,8)實現定義

+0

'foo(70,72)'和'foo(-2,-2)'顯示爲'Equal' –

+0

@Manav:foo(-2,-2)顯示了等於和不等於我。 – PlasmaHH

+0

@Manav:簡單地說,這也是未定義的行爲,因爲移動的位數比實際佔用的多,行爲未定義 – Omkant

4

嘗試一些更值:

1,0: Equal 
0,0: Not Equal 
1,1: Not Equal 
2,2: Not Equal 
3,3: Not Equal 

表明它不是一個平等的檢查都沒有。

該表達式具有未定義的行爲,因爲它執行a的兩個非順序修改。如果我們假設你的編譯器會計算它,因爲如果有左移後的序列點,即

b <<= a; 
a >>= b; 
return a ? 1 : 0; 

那麼它很容易看出,除非b爲零,這總是返回零,除非的左移溢出,在這種情況下,行爲再次未定義。