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为什么当一个论点是肯定的而另一个是否定的时它会失败?function 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

为什么当一个论点是肯定的而另一个是否定的时它会失败?函数 foo() 中的解决方法是什么可以正确显示所有情况下的结果,即所有否定和肯定参数?

答案在于 C99 标准(ISO C99:6.5.7 位移位运算符):

/4。的结果E1 << E2E1左移的E2位位置;空出的位用零填充。如果E1具有无符号类型,则结果的值为 ,以E1 × 2E2比结果类型中可表示的最大值大一为模减少。如果E1具有带符号类型和非负值,并且E1 × 2E2可以在结果类型中表示,那么这就是结果值;否则,行为未定义。

未定义的行为foo(-2,-2)也是如此。

/5。结果E1 >> E2E1右移的E2位位置。如果E1有无符号类型或E1有符号类型和非负值,则结果的值是 的商的整数部分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

表明它根本不是平等检查。

该表达式具有未定义的行为,因为它对a. 如果我们假设您的编译器评估它就好像在左移之后有一个序列点,即

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

那么很容易看出,除非b为零,否则它总是返回零,除非左移溢出,在这种情况下,行为再次未定义。

于 2012-12-19T12:19:22.683 回答