Странный результат после присвоения 2^31 32-битной целочисленной переменной со знаком и без знака

Как следует из заголовка вопроса, присваивание 2^31 знаковому и беззнаковому 32-битовая целочисленная переменная дает неожиданный результат.

Вот короткая программа (вC++), которую я сделал, чтобы посмотреть, что происходит:

#include <cstdio>
using namespace std;

int main()
{
    unsigned long long n = 1<<31;
    long long n2 = 1<<31;  // this works as expected
    printf("%llu\n",n);
    printf("%lld\n",n2);
    printf("size of ULL: %d, size of LL: %d\n", sizeof(unsigned long long), sizeof(long long) );
    return 0;
}

Вот результат:

MyPC / # c++ test.cpp -o test
MyPC / #./test
18446744071562067968      <- Should be 2^31 right?
-2147483648               <- This is correct ( -2^31 because of the sign bit)
size of ULL: 8, size of LL: 8

Затем я добавил к ней еще одну функцию p(),:

void p()
{
  unsigned long long n = 1<<32;  // since n is 8 bytes, this should be legal for any integer from 32 to 63
  printf("%llu\n",n);
}

При компиляции и работает, вот что смутило меня еще больше:

MyPC / # c++ test.cpp -o test
test.cpp: In function ‘void p()’:
test.cpp:6:28: warning: left shift count >= width of type [enabled by default]
MyPC / #./test 
0
MyPC /

Почему компилятор должен жаловаться на то, что счетчик сдвига влево слишком велик?sizeof(unsigned long long)возвращает 8, значит ли это, что 2^63-1 является максимальным значением для этого типа данных?

Мне пришло в голову, что, возможно, n*2 и n<<1 не всегда ведут себя одинаково, поэтому я попробовал это.:

void s()
{
   unsigned long long n = 1;
   for(int a=0;a<63;a++) n = n*2;
   printf("%llu\n",n);
}

Это дает правильное значение 2^63 в качестве вывода, которое9223372036854775808(Я проверил это с помощью Python). Но что плохого в том, чтобы заниматься левым дерьмом?

Арифметический сдвиг влево на n эквивалентен умножению на 2 n (при условии, что значение не переполняется)

--Википедия

Значение не переполняется, появится только знак минус, поскольку значение равно 2^63 (установлены все биты ).

Я до сих пор не могу понять, что происходит со сдвигом влево, кто-нибудь может объяснить это?

PS:Эта программа была запущена на 32-битной системе под управлением linux mint (если это поможет)

5
задан Rushil Paul 2 April 2012 в 08:48
поделиться