Преобразовать битовый набор & lt; a & gt; для подписи int с & lt; 32 & gt;

Я читал вопрос конвертировать набор битов в 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)

4

Решение

Как насчет чего-то такого:

#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;
}

(Вдохновленный Знак, выходящий из постоянной битовой ширины.)

2

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

Создайте маску, имеющую единицы в оставшихся старших битах, и ИЛИ со значением без знака из приведения, когда самый старший бит в наборе битов установлен в 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 биты установлены в 1s. ~ инвертирует его, создавая двоичное дополнение к значению вашего набора битов.

Demo.

1

Вам нужно расширение знака

#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;
0
По вопросам рекламы [email protected]