почему сдвиг влево с переменными дает результат, отличный от константы?

После компиляции приведенного ниже кода я получил странный результат: a = 1, а b = 0. Кто-нибудь может объяснить, что происходит за кулисами?

#include<iostream>
using namespace std;

int main(){

int n=32;
int a=1<<n;  //turns out a=1
int b=1<<32; //turns out b=0
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
}

5

Решение

Стандарт не определяет, или, скорее, он определяет его как «неопределенное поведение», что происходит в случае левого смещения за пределами размера целочисленного типа. [Причиной такого неопределенного поведения является то, что различные аппаратные средства могут вести или не вести себя одинаково, например, 32-битный сдвиг влево].

В первом случае [хотя бы без оптимизации] компилятор генерирует инструкции для расчета 1 << 32 — который на x86 превращается в 1 << (32 & 31) который так же, как 1 << 0 — таким образом вы получаете 1.

Во втором случае компилятор вычислит само значение, которое превращается в переполнение и дает ноль.

Вполне вероятно (но не обязательно), что если вы измените параметры компилятора для оптимизации кода, он даст ноль для обоих случаев. И вы получите желаемое поведение, если будете делать цикл с меньшими сменами (хотя вы можете найти «интересное» поведение с тем фактом, что число становится отрицательным, поэтому лучше всего использовать unsigned для всех операций смены) ,

5

Другие решения

Потому что вы вызываете неопределенное поведение. Сдвиг большего количества битов, чем существует в типе, не определен для какого-либо конкретного поведения.

Увидеть http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html?m=1

Величина слишком большого сдвига: сдвиг uint32_t на 32 или более бит
не определено. Я предполагаю, что это произошло потому, что
Операции сдвига на разных процессорах делают с этим разные вещи:
Например, X86 усекает 32-битную величину сдвига до 5 бит (поэтому сдвиг на
32-битное — это то же самое, что сдвиг на 0 бит), но PowerPC усекает
32-битное смещение составляет 6 бит (поэтому смещение на 32 дает ноль).
Из-за этих аппаратных различий поведение полностью
не определяется C (таким образом, сдвиг на 32 бита в PowerPC может отформатировать ваш
жесткий диск, это не гарантированно производить ноль). Цена
устранение этого неопределенного поведения заключается в том, что компилятор должен
выдать дополнительную операцию (например, ‘и’) для переменных сдвигов, которые
сделает их вдвое дороже на обычных процессорах.

5