djp*_*jp3 2 c debugging gcc clang
我正在编写一些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");
}
}
Run Code Online (Sandbox Code Playgroud)
如果我这样编译它,我得到一个传递结果
$ gcc tester.c -o tester
$ ./tester
passes
Run Code Online (Sandbox Code Playgroud)
如果我这样编译它会得到一个失败的结果
$ gcc -O1 tester.c -o tester
$ ./tester
fails
Run Code Online (Sandbox Code Playgroud)
问题是
x <= TMax_n
Run Code Online (Sandbox Code Playgroud)
仅在优化的情况下评估为false.
这是我的平台详细信息:
$ 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
Run Code Online (Sandbox Code Playgroud)
您的平台显然使用32位int
类型.0x20
是32
,这意味着1 << (n-1)
你的函数内部试图1
逐31
位移动.该行为未定义,因为此表达式具有签名类型(1
具有类型int
),并且值2 2 31在其中不可表示.
6.5.7按位移位运算符
4 E1 << E2的结果是E1左移E2位位置; 腾出的位用零填充.[...]如果E1具有带符号类型和非负值,并且E1×2 E2可在结果类型中表示,那么这就是结果值; 否则,行为未定义.
您所观察到的是未定义行为的后果.看到它的表现形式依赖于编译器的优化设置并没有什么异常.
归档时间: |
|
查看次数: |
51 次 |
最近记录: |