我对这段代码的MSVC和clang之间的行为差异感到困惑:
#include <iostream>
#include <cstdint>
int main() {
int64_t wat = -2147483648;
std::cout << "0x" << std::hex << wat << std::endl;
return 0;
}
Visual Studio 2010,2012和2013(在Windows 7上)全部显示:
0x80000000
但是clang 503.0.40(在OSX上)显示:
0xffffffff80000000
根据C ++标准,正确的行为是什么?文字应该是零扩展还是符号扩展到64位?
我知道int64_t wat = -2147483648LL;
会在两个编译器上产生相同的结果,但我想知道没有文字后缀的正确行为。
答案 0 :(得分:13)
初始化左侧的类型无关紧要。表达式-2147483648
由其自身独立解释。
Literal 2147483648
没有后缀,这意味着编译器会首先尝试将其解释为int
值。在您的平台上int
显然是32位类型。值2147483648
超出了带符号的32位整数类型的范围。编译器需要使用更宽的有符号整数类型来表示值(如果有的话)(在int
,long int
,long long int
序列中,最后一个可以从C正式获得++ 11 on)。但是,如果没有足够宽的有符号整数类型可用,则行为未定义
在MSVC中,历史long int
具有与int
相同的宽度,尽管在更高版本的MSVC中也支持64位long long int
。但是,即使在VS2013(支持long long int
)中,我也会得到
warning C4146: unary minus operator applied to unsigned type, result still unsigned
响应您的初始化。这意味着MSVC仍然坚持使用古老的C89 / 90整数字面解释规则(其中类型选自int
,long int
,unsigned long int
序列)。
请注意,MSVC不是正式的C ++ 11编译器。所以正式地说它不必尝试long long int
。这种类型在C ++ 11之前的语言中并不正式存在。从这个角度来看,MSVC在这种情况下没有足够大的有符号整数类型,并且行为是未定义的。在未定义行为提供的自由中,使用C89 / 90规则进行整数字面解释是完全合理的。