我有一个使用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 ++中的警告。
答案 0 :(得分:11)
根据标准中的[lex.icon],十六进制文字0xFFF0000000000000LL
的类型为unsigned long long
,因为该值不适合long long
(参见{{3}有关此内容的更多信息,请参见{}和<{p}}。
这意味着G ++的警告是正确的,您要将long long result
与unsigned 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 ++错了。