#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
请解释一下,为什么这种平等检查适用于某些价值集,而不适用于其他价值集。里面发生了什么?
答案 0 :(得分:7)
这不是一次平等检查(你可以从结果中清楚地看到),这是一项任务:
a = ( a >> ( b = b << a ) ); //results in UB for negatives
等式检查很简单
a == b;
答案 1 :(得分:5)
为什么当一个论点是积极的而另一个是否定的时候会失败? 函数foo()中的解决方法是为所有情况正确显示结果,即所有消极和正面参数?
答案在于C99-Standard(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)
是实现定义的。
答案 2 :(得分: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
为零,否则它总是返回零,除非左移溢出,在这种情况下行为再次未定义。