Почему я получаю случайные результаты с помощью оператора Shift (C ++)?

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

Входные данные:

std::size_t
foo1 = 100000 << 20,
foo2 = 200000 << 20,
foo3 = 300000 << 20,
foo4 = 400000 << 20;
std::cout << "foos1-4:";
std::cout << foo1;
std::cout << foo2;
std::cout << foo3;
std::cout << foo4;

выходы:

foos1-4:
1778384896
18446744072971354112
1040187392
18446744072233156608

Я знаю, что это какая-то ошибка переполнения, но (насколько мне известно, ограниченные знания) size_t не должна иметь их. Из того, что я понимаю, size_t — это целочисленный тип без знака, который может содержать практически неограниченное число целых чисел.

Из того, что я понимаю для операторов сдвига битов, этот код должен умножать число на 2 ^ 20 (1048576). Ссылки на другие страницы этого сайта:
Что такое операторы побитового сдвига (bit-shift) и как они работают?

Примечание. Я решил, что foo1 является ошибкой переполнения с усечением 32 двоичных цифр, но все остальные мне кажутся совершенно случайными.

От http://en.cppreference.com/w/cpp/types/size_t:
std :: size_t может хранить максимальный размер теоретически возможного объекта любого типа (включая массив). Исходя из этого, я предполагаю, что проблема должна заключаться либо в том, как объявлены целые числа, либо в том, как работает сдвиг битов.

В чем дело?

2

Решение

Проблема не в std::size_t но int литералы используются. Вы можете сделать их достаточно долго, используя UL постфикс как здесь:

#include <iostream>

int main()
{
std::size_t
foo1 = 100000UL << 20,
foo2 = 200000UL << 20,
foo3 = 300000UL << 20,
foo4 = 400000UL << 20;
std::cout << "foos1-4:" << std::endl;
std::cout << foo1 << std::endl;
std::cout << foo2 << std::endl;
std::cout << foo3 << std::endl;
std::cout << foo4 << std::endl;
}

Выход:

foos1-4:
104857600000
209715200000
314572800000
419430400000

Live Demo


Также обратите внимание, что компилятор выдает предупреждение именно об этом:

main.cpp:6:19: warning: result of '(100000 << 20)' requires 38 bits to represent, but 'int' only has 32 bits [-Wshift-overflow=]
foo1 = 100000 << 20,
~~~~~~~^~~~~
main.cpp:7:19: warning: result of '(200000 << 20)' requires 39 bits to represent, but 'int' only has 32 bits [-Wshift-overflow=]
foo2 = 200000 << 20,
~~~~~~~^~~~~
main.cpp:8:19: warning: result of '(300000 << 20)' requires 40 bits to represent, but 'int' only has 32 bits [-Wshift-overflow=]
foo3 = 300000 << 20,
~~~~~~~^~~~~
main.cpp:9:19: warning: result of '(400000 << 20)' requires 40 bits to represent, but 'int' only has 32 bits [-Wshift-overflow=]
foo4 = 400000 << 20;
~~~~~~~^~~~~
11

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

Других решений пока нет …

По вопросам рекламы [email protected]