The question asks,
Let int x = 1, find a value for int y where the following statement will return false:
(x < y) == (-x > -y)
I know the answer should be 4 bytes long (8 hex digits), but I don't know how to approach the question.
The question asks,
Let int x = 1, find a value for int y where the following statement will return false:
(x < y) == (-x > -y)
I know the answer should be 4 bytes long (8 hex digits), but I don't know how to approach the question.
There isn't any value for y
for which the expression is false. If we compile this:
int test(int y)
{
int x = 1;
return (x < y) == (-x > -y);
}
both gcc and clang with optimization enabled will generate this code:
test(int):
mov eax, 1
ret
Any other answer that thinks is smart most likely uses overflow and is actually Undefined Behavior or misunderstands some C fundamentals.
Actually there are no values for either x
or y
for which the expression is false:
int test(int x, int y)
{
return (x < y) == (-x > -y);
}
gives the same:
test(int, int):
mov eax, 1
ret
It seems some people miss the implication and significance of the fact that the compilers transform the expression into return 1
. This is proof that the compiler has definitely proven that there is no valid input for which the expression is false. Otherwise it would not have been allowed to do this optimization.
Find a value y such (x < y) == (-x > -y) will be false, when x is a signed integer and x=1?
When unsigned y = 0
.
int main(void) {
int x = 1;
unsigned y = 0;
printf("%u\n", (x < y) == (-x > -y));
return 0;
}
Output
0
Oops did not see the "find a value for int y
(in hex)" until later.
Leave posted as wiki since it answer the title question, but gets disallowed in the details.
The answer is INT_MIN == -INT_MIN
, I think you have already known how it work.
But if you want do an experiment and feels bad for compiler optimization,
you can use noclone
attribute to prevent compiler do constant propgation,
and noinline
attribute let less()
is a black box for 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));
}
If int
is defined as 32 bit two-complement value, then value 0x80000000
will fail the comparison. The reason is that two-complement values has one more value in the negative side than in the positive side. Any positive value can be converted to negative, but not all negative values can be converted to positive.
So, for the above mentioned value, y
and -y
are actually the same value and the first comparison (x < y)
will yield "false" where (-x > -y)
will yield "true", making the whole expression "false".
But it wouldn't happen if, as in the answer from @bolov, the compiler optimizes the function.