Согласно 5.8 / 2 (по общему признанию в C ++ 98, который является всем, к чему я имею доступ):
Значение E1 << E2 равно E1
(интерпретируется как битовый паттерн)
сдвинутые влево битовые позиции E2; освобождено
биты заполнены нулями. Если E1 имеет
тип без знака, значение результата
E1 умножается на количество 2
поднял на мощность Е2, уменьшил по модулю
ULONG_MAX + 1, если E1 имеет тип unsigned
long, UINT_MAX + 1 в противном случае. </p>
Из этого мне кажется, что он отлично определен для левого смещения. Что не определено, так это представление значений со знаком (например, дополнения до двух), поэтому числовое значение результата является реализацией, определенной для отрицательных значений.
Это отличается от сдвига вправо, когда освобожденные биты могут быть нулем или заполнены в зависимости от представления значений со знаком.