Использование Visual Studio 2015 C ++, обновление 14.0.25431.01 3. В моем коде неожиданное поведение. Скомпилируйте и запустите с 64-битной версией:
#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;
}
}
Я ожидаю что a
а также b
имеют то же значение, но когда я запускаю это, я получаю этот вывод:
4224838037 32bit
4224838037 64bit
4154708778 32bit
8449676074 64bit
Похоже, компилятор заменяет 32-битное умножение на 64-битное умножение. Это разрешено делать, или это ошибка компилятора? И g ++, и clang дают мне ожидаемые числа.
РЕДАКТИРОВАТЬ: я обновил свой код с более простой версией, которая имеет ту же проблему. Также, Я только что отправил отчет об ошибке.
Я мог бы воспроизвести это на VS2010, и непосредственная причина заключается в следующем:
add ebx, 5BD1E995h ; this is x
add rdi, 5BD1E995h ; this is a 64bit version of x
Так как это 64-битное дополнение, оно просто переносится в старшие 32 бита. По крайней мере, это имеет больше смысла, чем вызывать 64-битное умножение, это может быть ключевой случай в исключении индукционных переменных, но это всего лишь предположение.
Также забавно, что он даже не сохраняет актерский состав, неправильно компилируя его. Правильное значение находится прямо в rbx
,
Похоже, что это исправление устраняет проблему, по крайней мере, для VS 2015:
Но, похоже, VS 2008, 2010, 2013 все еще подвержены этой ошибке.
Источники: