C语言 当x是有符号整数且x=1时,找到一个值y使得(x < y)==(-x > -y)为假?

hgncfbus  于 2023-11-16  发布在  其他
关注(0)|答案(4)|浏览(133)

问题是,
假设int x = 1,找到int y的一个值,其中以下语句将返回false:(x < y) == (-x > -y)
我知道答案应该是4字节长(8个十六进制数字),但我不知道如何处理这个问题。

bq3bfh9z

bq3bfh9z1#

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

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

字符串
gcc和clang在启用优化后都会生成以下代码:

test(int):
        mov     eax, 1
        ret


任何其他认为是聪明的答案最有可能使用溢出,实际上是未定义的行为或重复一些C的基本原理。
实际上,对于xy,没有表达式为false的值:

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


给出相同的:

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


似乎有些人忽略了编译器将表达式转换为return 1这一事实的含义和意义。这证明了编译器已经明确证明了不存在表达式为false的有效输入。否则它不会被允许进行这种优化。

iecba09b

iecba09b2#

当x是有符号整数且x=1时,求一个y值使得(x < y)==(-x > -y)为假。
unsigned y = 0

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

字符串
输出

0


哎呀,直到后来才看到“查找**int y**(十六进制)的值”。
离开张贴为维基,因为它回答了标题问题,但得到不允许的细节。

qlzsbp2j

qlzsbp2j3#

答案是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));
}

字符串

q43xntqr

q43xntqr4#

如果int定义为32位二进制补码值,则值0x80000000将无法进行比较。原因是二进制补码值的负端比正端多一个值。任何正值都可以转换为负值,但不是所有负值都可以转换为正值。
因此,对于上述值,y-y实际上是相同的值,第一次比较(x < y)将产生“false”,而(-x > -y)将产生“true”,使整个表达式为“false”。
但如果编译器优化了函数,就不会发生这种情况,就像@bolov的回答一样。

相关问题