在我的mac环境中遇到此问题,其中gcc版本如下所示:
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
Run Code Online (Sandbox Code Playgroud)
代码段来自其中一个函数.
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;
}
Run Code Online (Sandbox Code Playgroud)
a等于x,但是为什么它们在与TMax_n比较时有不同的行为?
更新:
此代码段中的所有数据类型都是int.
更新2:
感谢大家.我刚刚在ubuntu机器上尝试了相同的代码,并且工作正常.它只停留在我的MAC上.这是一个与编译器有关的问题.
这似乎是由于表达内未定义的行为(1 << (n-1)) - 1,特别是在(1 << (n-1))作为1被作为一个处理的int(可能是32位),和表达(1 << (n-1))然后产生一个值,该值是由一个没有表示的最大值以上 int.所以这个(中间)结果导致有符号整数算术溢出,即UB(参见cppreference):
当有符号整数算术运算溢出时(结果不适合结果类型),行为是未定义的:它可能根据表示的规则(通常是2的补码)回绕,它可能在某些平台上陷阱或由于编译器选项(例如GCC和Clang中的-ftrapv),或者可以由编译器完全优化.
所以它可能适用于某些编译器,它可能不适用于其他编译器.但是,如果你unsigned int在bitshift之前进行转换,溢出就会消失,你又回到了定义的(和预期的)行为:
(int) (((unsigned)1 << (n-1)) - 1)
Run Code Online (Sandbox Code Playgroud)
BTW:如果设置-ftrapv在"其他编译器选项"的C编译器,则表达式int TMin_n = -(1 << (n-1))并int TMax_n = (1 << (n-1)) - 1导致运行时异常(如EXC_BAD_INSTRUCTION).