Этот вопрос уже имеет ответ здесь:
Кажется, что я должен быть в состоянии выполнить сдвиг разряда в C/C++ больше чем на 32 бита, если левый операнд сдвига является длинным. Но это, кажется, не работает, по крайней мере, с g ++ компилятор.
Пример:
unsigned long A = (1L << 37)
дает
A = 0
который не является тем, что я хочу. Я пропускаю что-то, или разве это просто не возможно?
- J
Повторите попытку, используя переменную типа uint64_t
(из stdint.h
) вместо длинный
. uint64_t
гарантированно имеет длину 64 бита и должен вести себя так, как вы ожидаете.
A равно 0, потому что A имеет только 32 бита, поэтому, конечно, вы сдвигаете все биты влево, оставляя только 0 бит. Вам нужно сделать A 64-битным:
unsigned long long A = (1ULL << 37);
Или, если вы собираетесь использовать Visual C++:
unsigned __int64 A = (1ULL << 37);
Ну, это зависит от фактического размера типа long
(точнее, от его ширины в битах). Скорее всего, на вашей платформе long
имеет ширину 32 бита, поэтому в результате вы получите 0
(также см. P.S. ниже). Используйте более крупный тип. long long
, может быть?
P.S. В качестве дополнительного замечания, сдвиг типа на большее количество бит, чем его ширина (или равное количество бит), приводит к неопределенному поведению в C и C++ (C++ использует термин length вместо width). Так, вы не гарантированно получите 0
ни из 1L << 37
, ни из 1L << 32
на платформе, где long
имеет ширину 32.
Новый стандарт C++ вводит суффиксы LL и ULL для целочисленных литералов. Вы можете попробовать использовать их, поскольку все последние компиляторы поддерживают их. Но вы должны знать, что это не является частью текущего стандарта C++.
long long A = (1LL << 37)
В вашем случае вы ограничены базовыми типами языка. Общее решение для [квази] целых чисел произвольного размера - использование класса Integer в Crypto ++ .
Вы уверены, что long - это 64 бита в вашей конкретной ОС и компиляторе? Используйте stdint.h и попробуйте так:
#include <stdint.h>
uint64_t x = (1ULL << 37);