«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > ## Почему оператор правого сдвига демонстрирует неожиданное поведение при больших значениях сдвига?

## Почему оператор правого сдвига демонстрирует неожиданное поведение при больших значениях сдвига?

Опубликовано 4 ноября 2024 г.
Просматривать:703

## Why Does the Right Shift Operator Exhibit Unexpected Behavior with Large Shift Values?

Интригующее поведение оператора правого сдвига

Оператор правого сдвига (>>) демонстрирует необычное поведение при работе с большими значениями сдвига вправо. Рассмотрим следующую программу:

#include 
#include 

int foo(int a, int b)
{
   return a >> b;
}

int bar(uint64_t a, int b)
{
   return a >> b;
}

int main()
{
    std::cout > 32: " > 32) > (int)32: " > (int)32) 

Ожидаемый результат для foo(1, 32) будет 0, но, что удивительно, он возвращает 1. Это можно объяснить следующим:

Логический сдвиг против арифметического Shift

В архитектурах x86/x86-64 оператор сдвига вправо фактически выполняет логический сдвиг вправо, что означает, что он заполняет освободившиеся биты 0, независимо от знак левого операнда. Поведение аналогично использованию >>> b.

Оптимизация компилятора

В случае foo(1, 32) значение 32 преобразуется в int, который фактически усекается до 32 бит. Поскольку максимальное значение, которое может содержать int, равно 231-1, правый сдвиг по существу представляет собой >>> (32 % 32), который оценивается как 0.

Undefined Поведение

Соответствующий стандарт C гласит, что «поведение не определено» для сдвигов вправо со счетом, большим или равным ширине повышенного левого операнда. В этом случае и 1 >> 32, и (int)1 >> (int)32 имеют счетчик больше 32, что приводит к непредсказуемым результатам.

Разница с bar(1, 32)

Функциональная панель принимает 64-битное целое число без знака, ширина которого гарантированно превышает 32. Таким образом, неопределенное поведение не влияет на сдвиг вправо в строке.

Заключение

Поведение оператора правого сдвига становится неоднозначным при работе с большими значениями сдвига. На архитектурах x86/x86-64 выполняется логический сдвиг вправо, а на ARM может использоваться другая реализация. Из-за неопределенного поведения в переносимом коде следует избегать результатов сдвигов вправо со счетчиком, превышающим или равным ширине операнда.

Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3