与<不一致的结果和< =在C中有最大和最小值

时间:2017-02-03 01:35:10

标签: 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");
    }
}

如果我以这种方式编译它,我得到一个传递结果

$ 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

1 个答案:

答案 0 :(得分:5)

您的平台显然使用32位int类型。 0x2032,这意味着您的函数中的1 << (n-1)会尝试将1移位31位。行为未定义,因为此表达式具有签名类型(1具有类型int),并且值2 31 在其中无法表示。

  

6.5.7按位移位运算符

     

4 E1的结果&lt;&lt; E2是E1左移E2位位置;腾出的位用零填充。 [...]如果E1具有带符号类型和非负值,并且E1×2 E2 在结果类型中可表示,那么这就是结果值;否则,行为未定义。

您所观察到的是未定义行为的后果。看到它的表现形式依赖于编译器的优化设置并没有什么异常。