как ведет себя бинарный сдвиг влево после 30 сдвигов в с ++? - PullRequest
0 голосов
/ 24 апреля 2020

в C ++ int имеет 4 байта, что означает, что в памяти int он может хранить 32 бита, тогда как

int i = 1;
i = i<<32;
cout<<i<<endl;

выдаст мне следующую ошибку: -

main.cpp:7:5: warning: shift count >= width of type
      [-Wshift-count-overflow]
  i <<= 32;

, тогда как

  int i = 1;
    i = i<<31;
    cout<<i<<endl;

дает мне

./main
-2147483648

и

  int i = 1;
    i = i<<30;
    cout<<i<<endl;

дает мне

./main
1073741824

что происходит?

1 Ответ

1 голос
/ 24 апреля 2020

Давайте представим число в двоичном формате и посмотрим, что делает левый сдвиг.

for example

    if i = 5        // binary 101
    i<<1 becomes 10 // binary 1010
    i<<2 becomes 20 // binary 10100

and so on

Аналогично

    if i = 1          // binary 1
    i<<1 becomes 2    // binary 10
    i<<2 becomes 4    // binary 100
    i<<n becomes 2^n  // binary 1000...n times
    i<<30 becomes 2^30 // binary 1000000000000000000000000000000

Если вы заметите, что 2 ^ n потребует n + 1 бит хранить, что объясняет вашу первую ошибку. 2 ^ 32 потребуется 33 бита, а std int будет 32-битным, вы получите ошибку переполнения.

Теперь обратите внимание, что 2 ^ 30 занимает 31 бит, которые представляют собой количество битов, выделенных для представления значения int, поскольку 32-й бит является знаковым битом (чтобы различать guish между отрицательными и положительными числами).

Итак, когда вы делаете i << 31, старший разряд 1 перезаписывает бит знака, и мы получаем отрицательное значение. </p>

Отрицательные числа в c ++ представлены с использованием дополнения 2s. 2s дополнение к 2 ^ 31 для 32-битного значения -2147483648, это то, что вы видите.

Теперь я << 30, когда i == 1 равно 2 ^ 30 или 1073741824 </p>

...