Смещение 64-битного значения на 64 бита в C++ дает странные результаты

Возможный дубликат:
Проблема 64-битного сдвига

Я использую Visual Studio 2012 на 64-битной Windows 8, нацеливаясь на x64 в режиме отладки, используя AMD Phenom II.
Так в основном...

uint64_t Foo = 0xFFFFFFFFFFFFFFFF << 64;//Foo is now 0x0000000000000000
uint64_t Derp = 64;
uint64_t Bar = 0xFFFFFFFFFFFFFFFF << Derp;//Foo is now 0xFFFFFFFFFFFFFFFF

Использование более низкого значения, например 63, восстанавливает нормальное поведение.
Почему это происходит и как я могу обойти это?

Обновление: я переключился в режим выпуска. И вот, проблема исчезла, и оба вернули 0. Но проблема остается в режиме отладки, где я должен быть для отладки своего кода.

2 ответа

Решение

Операция сдвига имеет неопределенное поведение, если вы сдвигаете на значения, которые больше или равны ширине бита.

Из Раздела 5.8 p1 в проекте C++11:

Операнды должны быть целочисленного или незаданного типа перечисления, и выполняются интегральные преобразования. Тип результата - тип повышенного левого операнда. Поведение не определено, если правый операнд отрицательный, или больше или равен длине в битах повышенного левого операнда.

Я считаю, что смещение на размер целого числа или больше не определено в C++.

Ваш первый пример оценивается во время компиляции, так как он включает только константы. Ваш второй пример вычисляется во время выполнения процессором.

Вы можете разделить смену на две части:

uint64_t Bar = 0xFFFFFFFFFFFFFFFF << (Derp / 2);
Bar <<= Derp - (Derp / 2);
Другие вопросы по тегам