2017-02-28 277 views
14

使用Visual Studio 2015 C++,14.0.25431.01更新3.我的代码中有意外的行为。编译和64位运行,释放:将uint32_t转换为uint64_t会产生不同的值?

#include <iostream> 
#include <stdint.h> 

int main(int, char**) { 
    for (uint32_t i = 1; i < 3; ++i) { 
     uint32_t a = i * 0xfbd1e995; 
     uint64_t b = a; 

     std::cout << a << " 32bit" << std::endl; 
     std::cout << b << " 64bit" << std::endl; 
    } 
} 

我希望ab具有相同的值,但是当我运行此我得到这样的输出:

4224838037 32bit 
4224838037 64bit 
4154708778 32bit 
8449676074 64bit 

它看起来像编译器替换32位乘法与64位乘法。它允许这样做,还是这是一个编译器错误? g ++和clang都给了我期望的数字。

编辑:我更新了我的代码与更简单的版本,具有相同的问题。另外,I've just submitted a bug report

+0

用gcc和铿锵没有摄制。这绝对不应该发生。编辑:也没有与rextester VS的repro。 –

+0

不能用mingw和visual studio编译器重现。 – SingerOfTheFall

+0

你使用什么版本的VS?你编译了Release 64bit吗? – martinus

回答

7

我能重现此对VS2010,而直接原因是这样的:

add ebx, 5BD1E995h ; this is x 
add rdi, 5BD1E995h ; this is a 64bit version of x 

因为它是一个64位此外,它只会延续到高32位。这至少比召唤64位乘法更有意义,它可能是归纳变量消除的一个特例,但这只是猜测。

另外有趣的是,它甚至没有通过编译它来保存强制转换。正确的值在rbx

+1

为什么它使用“add”乘法?无论如何,[似乎没有出现在CL19](https://godbolt.org/g/i6Y9is)了。我只能用1540483477 –

+2

找到'imul'我认为编译器试图变得聪明,并将循环从0替换为50,其中循环计数器乘以常数,只添加常量。 – martinus

相关问题