考虑到 bitset 的位数可能少于目标类型,我正在编写一个将 bitset 转换为 int/uint 值的函数。
这是我写的函数:
template <typename T,size_t count> static T convertBitSetToNumber( const std::bitset<count>& bitset )
{
T result;
#define targetSize (sizeof( T )*CHAR_BIT)
if ( targetSize > count )
{
// if bitset is 0xF00, converting it as 0x0F00 will lose sign information (0xF00 is negative, while 0x0F00 is positive)
// This is because sign bit is on the left.
// then, we need to add a zero (4bits) on the right and then convert 0xF000, later, we will divide by 16 (2^4) to preserve sign and value
size_t missingbits = targetSize - count;
std::bitset<targetSize> extended;
extended.reset(); // set all to 0
for ( size_t i = 0; i != count; ++i )
{
if ( i < count )
extended[i+missingbits] = bitset[i];
}
result = static_cast<T>( extended.to_ullong() );
result = result >> missingbits;
return result;
}
else
{
return static_cast<T>( bitset.to_ullong() );
}
}
和“测试程序”:
uint16_t val1 = Base::BitsetUtl::convertBitSetToNumber<uint16_t,12>( std::bitset<12>( "100010011010" ) );
// val1 is 0x089A
int16_t val2 = Base::BitsetUtl::convertBitSetToNumber<int16_t,12>( std::bitset<12>( "100010011010" ) );
// val2 is 0xF89A
注意:请参阅与 Ped7g 的评论/交换,上面的代码是正确的并保留位符号,并对有符号或无符号位进行 12->16 位转换。但是,如果您正在研究如何在签名对象上将 0xABC0 偏移到 0x0ABC,那么答案可以帮助您,所以我不会删除这个问题。
uint16
在用作目标类型时查看程序的工作原理,如下所示:
uint16_t val = 0x89A0; // 1000100110100000
val = val >> 4; // 0000100010011010
但是,使用时失败int16_t
,因为0x89A0 >> 4
is0xF89A
而不是 expected 0x089A
。
int16_t val = 0x89A0; // 1000100110100000
val = val >> 4; // 1111100010011010
我不明白为什么 >> 运算符有时会插入 0 有时会插入 1。而且我不知道如何安全地执行我的函数的最终操作(result = result >> missingbits;
在某些时候一定是错误的......)