Смещение 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);