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