我需要从字节数组 (std::vector) 中提取内容到位集。内容可能跨越两个字节。
这是我的单元测试:
std::vector<uint8_t> val = { 0xAB, 0xCD, 0xEF }; // is 101010111100110111101111
std::bitset<4> a = extractToBitSet<4>( val, 0 ); // should be 0x0A: 1010
std::bitset<8> bc = extractToBitSet<8>( val, 4 ); // should be 0xBC: 10111100
std::bitset<12> def = extractToBitSet<12>( val, 12 ); // should be 0x0DEF: 110111101111
CPPUNIT_ASSERT( a.to_string() == "1010" );
CPPUNIT_ASSERT( bc.to_string() == "10111100" );
CPPUNIT_ASSERT( def.to_string() == "110111101111" );
unsigned long aVal = a.to_ulong();
unsigned long bcVal = bc.to_ulong();
unsigned long defVal = def.to_ulong();
CPPUNIT_ASSERT( aVal == 0x0A );
CPPUNIT_ASSERT( bcVal == 0xBC );
CPPUNIT_ASSERT( defVal == 0x0DEF );
我想到了这个解决方案:
template<size_t _Count> void reverseBitSet( std::bitset<_Count>& bitset )
{
bool val;
for ( size_t pos = 0; pos < _Count/2; ++pos )
{
val = bitset[pos];
bitset[pos] = bitset[_Count-pos-1];
bitset[_Count-pos-1] = val;
}
}
template<size_t _Count> std::bitset<_Count> extractToBitSet( const std::vector<uint8_t>& data, size_t offset )
{
std::bitset<_Count> res;
size_t pos = 0;
uint8_t tempVal;
std::bitset<8> tempBitSet;
while ( pos < _Count )
{
tempVal = data[ (offset + pos)/8 ];
tempBitSet = tempVal;
reverseBitSet( tempBitSet );
res[pos] = tempBitSet[(offset + pos)%8];
++pos;
}
reverseBitSet( res );
return res;
}
它有效(我的测试通过),但它似乎非常低效,因为所有这些临时位集都被创建+许多反向操作。
有没有更优雅的方式来做到这一点?
最佳答案
为什么要倒车?您可以根据您正在执行的特定操作,随时显式设置每一位。只有一个循环:
template <size_t N>
std::bitset<N> extract(std::vector<uint8_t> const& vs, size_t offset) {
std::bitset<N> res;
for (size_t i = 0; i < N; ++i) {
size_t full_off = offset + i;
auto& byte = vs[full_off / 8];
auto bit = byte & (1 << (7 - (full_off % 8)));
res.set(N-i-1, bit);
}
return res;
}
关于c++ - 将跨字节数组内容提取到 std::bitset,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39350487/