Q:

При каких условиях в C битовый сдвиг влево для знакового целого приводит к неопределенному поведению?

Ясное дело, что << и >> не должны принимать справа отрицательное число, но дальше я ничего не понял.

A:

Вот что пишет стандарт:

Значение результата операции E1 << E2 есть значение E1, сдвинутое влево на E2 битовых позиций; биты, остающиеся свободными, заполняются нулями. Если тип E1 беззнаковый, то значение результата есть E1×2E2, взятое по модулю, на единицу большему, чем максимальное значение, представимое результирующим типом.
В противном случае, если E1 имеет знаковый тип и неотрицательное значение, а значение E1×2E2 представимо в соответствующем результирующему типу беззнаковом типе, то это значение, преобразованное к результирующему типу, и служит результирующим значением; в противном случае поведение программы не определено.

Так понятнее? :)

A:

Если под "сдвигом для знакового целого" подразумевается сдвиг, в котором "знаковым целым" является левый операнд, то стоит помнить, что левый операнд сдвига подвергается integer promotions. То есть даже если в выражении a << b значение a является знаковым, на некоторых экзотических платформах оно может стать беззнаковым после integer promotions.
Поэтому далее будем рассматривать выражение a << b, где a - значение после integer promotions и оно по-прежнему знаковое.
Битовый сдвиг влево a << b для знакового целого a приводит к неопределенному поведению когда

b < 0
Значение b превосходит битовую ширину a или равно ей
a < 0
При сдвиге произошло переполнение, т.е. значение a*2b (вычисленное математически верно) не помещается в диапазон типа a

Первые два пункта относятся ко всем сдвигам.
Выражаясь более приземленным языком, последние два пункта говорят, что нельзя двигать влево единицу в знаковом бите и нельзя вдвигать справа единицу в знаковый бит.

