-gsign-compare警告用g ++表示

时间:2013-05-30 11:08:43

标签: c++ c++11 g++

我有一个使用64位整数比较的代码。它看起来类似于以下内容:

#include <cstdio>

long long getResult()
{
    return 123456LL;
}

int main()
{
    long long result = getResult();

    if (result > 0x000FFFFFFFFFFFFFLL
        || result < 0xFFF0000000000000LL)
    {
        printf("Something is wrong.\n");

        if (result > 0x000FFFFFFFFFFFFFLL
            || result < -4503599627370496LL)
        {
            printf("Additional check failed too.\n");
        }
        else
        {
            printf("Additional check went fine.\n");
        }
    }
    else
    {
        printf("Everything is fine.\n");
    }

    return 0;
}

当这个代码用g ++编译时(在Ubuntu 12.04 x64:4.6.3,4.6.4,4.7.3,4.8.0上尝试了不同的版本),带有标志-Wall -pedantic -std = c ++ 0x test。 cpp -o test我得到第一个if语句的第二行的-Wsign-compare警告(来自g ++ - 4.8的输出):

test.cpp:13:17: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 || result < 0xFFF0000000000000LL)
             ^

当测试程序运行时,我得到两行文字:

Something is wrong.
Additional check went fine.

使用带有x86或x64架构的默认项目选项的MS Visual Studio 11 Express Update 2在Windows上编译相同的代码时,我既没有得到警告也没有得到此输出,而是输出为:

Everything is fine.

这是代码中的问题吗?如果是的话,你能指出它吗?或者是使用编译器的问题?

在第一个if语句中为第二个常量添加额外的类型转换会删除g ++中的警告。

1 个答案:

答案 0 :(得分:11)

根据标准中的[lex.icon],十六进制文字0xFFF0000000000000LL的类型为unsigned long long,因为该值不适合long long(参见{{3}有关此内容的更多信息,请参见{}和<{p}}。

这意味着G ++的警告是正确的,您要将long long resultunsigned long long字面值进行比较。

显然,作为无符号值,123456LL小于0xFFF0000000000000LL,因此G ++的结果也是正确的。

MSVC似乎有一个错误[编辑:或因兼容性原因而行为不同,请参阅注释],因为此断言失败:

static_assert(0xFFF0000000000000LL > 0, "big number is big");

MSVC提供长文字0xFFF0000000000000LL类型,如MSVC接受的无效代码所示:

auto i = 0xFFF0000000000000LL;
long long& l = i;

应该编译没有错误的C ++ 03示例是:

template<typename T>
void f(T t)
{
    unsigned long long& l = t;
}

int main()
{
    f(0xFFF0000000000000LL);
}

GCC,Clang,Intel和Solaris CC都是正确的,VC ++错了。