2017-02-28 65 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

相關問題