Я читал вопрос конвертировать набор битов в int в c ++ и подумал, эй, это не работает, я уже попробовал. Но потом я начал пытаться и быстро обнаружил, что:
#include <bitset>
#include <iostream>
int main()
{
std::bitset<31> b31(-1);
std::bitset<32> b32(-1);
std::cout<<static_cast<int>(b31.to_ulong())<<std::endl;
std::cout<<static_cast<int>(b32.to_ulong())<<std::endl;
return 0;
}
дает вывод
2147483647
-1
Итак, как я могу привести битовые наборы меньше 32 к целым числам со знаком?
ПОЯСНЕНИЕ: я хочу привести обратно к подписанному int с 10-значным значением, используемым при создании сохраненных наборов битов. «хранить подписанные целые числа в битах»
Я пробовал это с gcc 4.6.2, mingw32 на win 7, и тот же результат получается с броском в стиле c (int)
Как насчет чего-то такого:
#include <bitset>
#include <iostream>
template<std::size_t B>
long bitset_to_long(const std::bitset<B>& b) {
struct {long x:B;} s;
return s.x = b.to_ulong();
}
int main()
{
std::bitset<31> b31(-1);
std::bitset<32> b32(-1);
std::cout << bitset_to_long(b31) << std::endl;
std::cout << bitset_to_long(b32) << std::endl;
return 0;
}
(Вдохновленный Знак, выходящий из постоянной битовой ширины.)
Создайте маску, имеющую единицы в оставшихся старших битах, и ИЛИ со значением без знака из приведения, когда самый старший бит в наборе битов установлен в 1
, как это:
const int sz = 15;
std::bitset<sz> b(-1);
int num = static_cast<int>(b.to_ulong());
if (b[sz-1]) {
int mask = (1<<sz)-1;
num |= ~mask;
}
std::cout << num << std::endl;
выражение (1<<sz)
делает число только sz
бит установлен. (1<<sz)-1
делает маску с последним sz-1
биты установлены в 1
s. ~
инвертирует его, создавая двоичное дополнение к значению вашего набора битов.
Вам нужно расширение знака
#define BITLEN 31
#define SHIFT_AMOUNT (sizeof(int)*CHAR_BIT - BITLEN)
std::bitset<BITLEN> b31(-1);
int v = (static_cast<int>(b31.to_ulong()) << SHIFT_AMOUNT) >> SHIFT_AMOUNT;
std::cout << v << std::endl;