【发布时间】:2017-08-19 09:27:35
【问题描述】:
int x = random();
int y = random();
unsigned ux = (unsigned) x;
unsigned uy = (unsigned) y;
对于以下每个 C 表达式,你要指出是否 不是表达式总是产生 1。如果它总是产生 1,请描述基本的数学原理。否则,请给出一个使其产生 0 的参数示例。
A. (x<y) == (-x>-y)
B. ((x+y)<<4) + y-x == 17*y+15*x
C. ~x+~y+1 == ~(x+y)
D. (ux-uy) == -(unsigned)(y-x)
E. ((x >> 2) << 2) <= x
对于这些问题,我知道只有 A 可以产生 0,而其余的总是产生 1。
我知道这可能是错误的,我不是在寻找直接的答案,但我希望获得一些关于如何解决这些问题的一般知识/建议。
我有一位非常糟糕的教授,我一直在尝试在线查找资源,但我真的不知道从哪里开始或寻找什么。我知道无符号/二进制补码算术和位移的基础知识,但我不知道如何应用它来找到这些问题的反例。
【问题讨论】:
-
A 应始终为 1 ...
-
如果
x == INT_MIN(例如)可能不是因为-INT_MIN在使用二进制补码表示的机器上不能表示为int(几乎所有现代计算机都这样做)。在这种情况下,表达式将导致未定义的行为(不仅仅是具有未指定的值)。 -
事实上,对于除 D 之外的所有表达式,都存在
x和y的值,它们会导致未定义的行为或具有未指定的值,从而使问题无法回答,因为它们可能或者可能不会为这些值产生0或完全做其他事情。我怀疑这本书不知道有符号整数溢出(也没有符号位移)的规则,只是假设编译器不会基于它们进行优化。根据这样的假设,FreeBSD 是 recently bitten。 -
哦,对于 D 也是如此,例如
y = INT_MIN、x = 1(导致表达式右侧的整数下溢,从而导致未定义的行为)。当我写最后一条评论时,我读到好像ux和uy被用于右侧和左侧。 -
@Wintermute 我刚刚用 D 的这些值进行了测试,它仍然适用于我。我认为我们假设该值会换行/被截断?不确定这是否是它起作用的原因。
标签: c bit-manipulation unsigned twos-complement