当 x 是有符号整数并且 x=1 时,找到一个值 y,这样 (x < y) == (-x > -y) 将为 false?

问题描述 投票:0回答:4

问题问,

令 int x = 1,找到 int y 的值,其中以下语句将返回 false:

(x < y) == (-x > -y)

我知道答案应该是 4 个字节长(8 个十六进制数字),但我不知道如何解决这个问题。

c undefined-behavior integer-overflow
4个回答
9
投票

y
没有任何值使得表达式为假。如果我们编译这个:

int test(int y)
{
    int x = 1;
    
    return (x < y) == (-x > -y);
}

启用优化的 gcc 和 clang 都会生成以下代码:

test(int):
        mov     eax, 1
        ret

任何其他认为聪明的答案很可能使用溢出,实际上是未定义的行为或误解了一些 C 基础知识。

实际上,

x
y
都没有值使得表达式为假:

int test(int x, int y)
{
    return (x < y) == (-x > -y);
}

给出相同的:

test(int, int):
        mov     eax, 1
        ret

似乎有些人忽略了编译器将表达式转换为

return 1
这一事实的含义和意义。这证明编译器已经明确证明不存在表达式为假的有效输入。否则就不会被允许做这个优化。


0
投票

当 x 是有符号整数并且 x=1 时,找到一个值 y,这样 (x < y) == (-x > -y) 将为 false?

unsigned y = 0
时。

int main(void) {
  int x = 1;
  unsigned y = 0;
  printf("%u\n", (x < y) == (-x > -y));
  return 0;
}

输出

0

哎呀直到后来才看到“找到

int y
的值(十六进制)”。

将其发布为 wiki,因为它回答了标题问题,但在细节方面不允许。


-1
投票

答案是

INT_MIN == -INT_MIN
,我想你已经知道它是如何工作的了。

但是如果你想做一个实验并且对编译器优化感觉不好, 您可以使用

noclone
属性来防止编译器进行常量传播, 和
noinline
属性让
less()
main()

的黑盒子
#include <limits.h>

__attribute__ ((noclone, noinline))
int less (int x, int y) {
  return x > y;
}

__attribute__ ((noclone, noinline))
int neg (int x) {
  return -x;
}

int main(void) {
  int x = 1, y = INT_MIN;
  return  less(x, y) == less(neg(y), neg(x));
}

-2
投票

如果

int
定义为32位补码值,则
0x80000000
值将无法比较。原因是二补值的负数比正数多一个值。任何正值都可以转换为负值,但并非所有负值都可以转换为正值。

因此,对于上述值,

y
-y
实际上是相同的值,第一次比较
(x < y)
将产生“假”,其中
(-x > -y)
将产生“真”,使整个表达式“假” .

但是,如果像 @bolov 的答案一样,编译器优化了该函数,则不会发生这种情况。

© www.soinside.com 2019 - 2024. All rights reserved.