Этот ответ для языка Си. В этом конкретном вопросе, похоже, есть тонкие различия в спецификации C ++.
Если x
является беззнаковым и , если n >= 0
и меньше, чем число битов значения в типе x
, x << n
действительно совпадает с умножением x
на n-я степень 2.
Если это вычисление переполнится, результат будет уменьшен по модулю наибольшего значения для типа x
плюс 1.
Если x
подписано, оно должно быть неотрицательным, результат не должен быть переполнен, иначе вы получите неопределенное поведение. Типичный случай неопределенного поведения на 32-битных архитектурах таков:
unsigned x = 1 << 31; /* undefined behavior: 1 is signed, 31 is too large */
Правильная версия:
unsigned x = 1U << 31; /* correct on 32 bit architectures */
Кстати, начиная с C ++ 14, в стандарте C ++ есть конкретное положение для этого самого случая:
значение a << b
умножается на 2 b , если оно представимо в беззнаковой версии возвращаемого типа (который затем преобразуется в подписанный: это делает законным создание INT_MIN
как 1 << 31
), иначе поведение не определено.
По второму вопросу x * 15
равно x << 4 - x
?
Ответ - нет, потому что x << 4 - x
анализируется как x << (4 - x)
.
Если вы заключите в скобки свое выражение, тогда действительно x * 15 == (x << 4) - x
.
Обратите внимание, что это не правильно для значений со знаком, потому что промежуточный результат x << 4
может переполниться для больших значений x
, для которых результат x * 15
не будет.