Сдвиг на размер типа является неопределенным поведением, в соответствии со стандартом C , § 6.5.7.3:
6.5.7 Операции побитового сдвига (...) Если значение правого операнда отрицательно или больше или равно ширине повышенного левого операнда, поведение не определено.
ВашКомпилятор должен предупредить вас об этом:
$ gcc shift.c -o shift -Wall
shift.c: In function ‘main’:
shift.c:5:5: warning: left shift count >= width of type [enabled by default]
shift.c:6:5: warning: right shift count >= width of type [enabled by default]
Если вы посмотрите на код ассемблера, который генерирует gcc, вы увидите, что он фактически вычисляет первые два результата во время компиляции.Упрощенно:
main:
movl $0, %esi
call printf
movl $0, %esi
call printf
movl -4(%rbp), %ecx ; -4(%rbp) is n
movl $-1, %esi
sall %cl, %esi ; This ignores all but the 5 lowest bits of %cl/%ecx
call printf
movl -4(%rbp), %ecx
movl $-1, %esi
shrl %cl, %esi
call printf