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

この同等性チェックが一部の値セットで機能し、他の値セットでは機能しない理由を説明してください。内部で何が起こっているのですか?

4

3 に答える 3

7

これは等価チェックではなく (結果から明らかなように)、代入です。

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

等価チェックは簡単です

a == b;
于 2012-12-19T11:48:27.597 に答える
5

1 つの引数が正で、別の引数が負の場合に失敗するのはなぜですか? すべてのケース、つまりすべての負の引数と正の引数に対して結果を正しく表示する関数 foo() の回避策は何ですか?

答えは C99-Standard (ISO C99 : 6.5.7 ビット単位のシフト演算子) にあります。

/4. の結果E1 << E2E1左シフトされたE2ビット位置です。空いたビットはゼロで埋められます。E1が unsigned 型の場合、結果の値はE1 × 2E2であり、結果の型で表現可能な最大値より 1 を法として減じられます。E1符号付きの型と非負の値を持ち、E1 × 2E2結果の型で表現できる場合、それが結果の値です。それ以外の場合、動作は未定義です。

未定義の動作foo(-2,-2)も同様です。

/5. の結果E1 >> E2E1右シフトされたE2ビット位置です。E1が unsigned 型の場合、またはsignedE1型で非負の値の場合、結果の値は の商の整数部分ですE1 / 2E2。符号付きの型と負の値を持つ場合E1、結果の値は実装定義です。

実装定義もそうfoo(-8,8)です。

于 2012-12-19T11:51:16.877 に答える
4

さらにいくつかの値を試します:

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

等価チェックではないことを示しています。

この式は、 の 2 つの順序付けられていない変更を実行するため、未定義の動作をしaます。左シフトの後にシーケンスポイントがあるかのようにコンパイラが評価すると仮定すると、つまり

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

がゼロでない限りb、左シフトがオーバーフローしない限り、これは常にゼロを返すことが非常に簡単にわかります。この場合、動作は再び未定義です。

于 2012-12-19T12:19:22.683 に答える