This problem is encountered in my mac environment where the gcc version is shown below:
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
The code segment is from one of the function.
int someFunction(int x, int n) {
int TMin_n = -(1 << (n-1));
int TMax_n = (1 << (n-1)) - 1;
int a = -2147483648;
printf("%s\n", x == a ? "true" : "false"); // true
printf("%s\n", x <= TMax_n ? "true" : "false"); // false
printf("%s\n", a <= TMax_n ? "true" : "false"); // true
printf("%d %d %d\n", TMin_n, x, TMax_n); // -2147483648 -2147483648 2147483647
return 0;
}
a is equal to x, but why they have different behavior when comparing to TMax_n?
UPDATE:
all the data types in this code segment is int.
UPDATE2:
Thanks everyone. I just tried the same code on an ubuntu machine and that works fine. It only stuck on my MAC.Seems that it is a problem related with the compiler.
It seems to be due to undefined behaviour within expression (1 << (n-1)) - 1, particularly in (1 << (n-1)), as 1 is treated as an int (probably 32 bit), and expression (1 << (n-1)) then yields a value which is one above the maximum value representable by an int. So this (intermediate) result leads to a signed integer arithmetic overflow, which is UB (cf. cppreference):
When signed integer arithmetic operation overflows (the result does not fit in the result type), the behavior is undefined: it may wrap around according to the rules of the representation (typically 2's complement), it may trap on some platforms or due to compiler options (e.g. -ftrapv in GCC and Clang), or may be completely optimized out by the compiler.
So it may work on some compilers, it may not work on others.
However, if you cast to unsigned int before bitshift, the overflow goes away and you are back in defined (and expected) behaviour:
(int) (((unsigned)1 << (n-1)) - 1)
BTW: if you set -ftrapv in the "other compiler options" for the C-compiler, then the expressions int TMin_n = -(1 << (n-1)) and int TMax_n = (1 << (n-1)) - 1 lead to a runtime exception (e.g. EXC_BAD_INSTRUCTION).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With