我正在编写一些C代码来查看整数的位表示。 在此过程中,我发现了基于优化设置返回不同结果的代码。我只是做错了什么,或者这是编译错误?
以下是代码:
#include <stdio.h>
int test(int x, int n)
{
int TMin_n = -(1 << (n-1));
int TMax_n = (1 << (n-1)) - 1;
return x >= TMin_n && x <= TMax_n;
}
int main(){
int x = 0x80000000;
int n = 0x20;
if(test(x,n)){
printf("passes\n");
}
else{
printf("fails\n");
}
}
如果我以这种方式编译它,我得到一个传递结果
$ gcc tester.c -o tester
$ ./tester
passes
如果我这样编译它会得到一个失败的结果
$ gcc -O1 tester.c -o tester
$ ./tester
fails
问题在于
x <= TMax_n
仅在优化的情况下评估为假。
以下是我的平台详情:
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin16.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
答案 0 :(得分:5)
您的平台显然使用32位int
类型。 0x20
为32
,这意味着您的函数中的1 << (n-1)
会尝试将1
移位31
位。行为未定义,因为此表达式具有签名类型(1
具有类型int
),并且值2 31 在其中无法表示。
6.5.7按位移位运算符
4 E1的结果&lt;&lt; E2是E1左移E2位位置;腾出的位用零填充。 [...]如果E1具有带符号类型和非负值,并且E1×2 E2 在结果类型中可表示,那么这就是结果值;否则,行为未定义。
您所观察到的是未定义行为的后果。看到它的表现形式依赖于编译器的优化设置并没有什么异常。