我正在尝试将 uint8_ts 数组的任何位置的 n 位复制到单个 64 位整数中。这是一个可行的解决方案,可以从数组的开头将任意数量的位复制到 64 位整数中,但我希望能够从数组的任何位置开始。
例如,我可能想复制数组的第 2 位到第 11 位: {7, 128, 7}
在二进制中是: 00000111 1000000 00000111
我想要一个有值的整数: 0001111000
std::uint64_t key_reg(std::uint8_t* bytes, std::size_t n)
{
std::uint64_t reg = 0;
// The amount of bits that fit into an entire element of an array
// ex, if I'm copying 17 bits, even_bytes == 2
std::size_t even_bytes = (n - (n % 8)) / 8;
// what's left over after the even bytes
// in this case, remainder == 1
std::size_t remainder = n - even_bytes * 8;
// copy each byte into the integer
for(std::size_t i = 0; i < even_bytes; ++i)
if(remainder)
reg |= (std::uint64_t)bytes[i] << (8 * (even_bytes - i));
else
reg |= (std::uint64_t)bytes[i] << (8 * (even_bytes - i - 1));
// if there is an uneven number of bits, copy them in
if(remainder)
reg |= (std::uint64_t)bytes[even_bytes];
return reg;
}
你知道如何实现吗
std::uint64_t key_reg(std::uint8_t* bytes, std::size_t pos, std::size_t n);
我认为没有人会回答得这么快,所以这是我想出的相同风格的解决方案。我在 stackoverflow 上找到了这个 bitfieldmask 函数,但我找不到问题来归功于作者。
template<typename R>
static constexpr R bitfieldmask(unsigned int const a, unsigned int const b)
{
return ((static_cast<R>(-1) >> (((sizeof(R) * CHAR_BIT) - 1) - (b)))
& ~((1 << (a)) - 1));
}
std::uint64_t key_reg(std::uint8_t* bytes, std::size_t pos, std::size_t n)
{
std::uint64_t reg = 0;
std::size_t starting_byte = (pos < 8) ? 0 : ((pos - (pos % 8)) / 8);
std::size_t even_bytes = (n - (n % 8)) / 8;
std::size_t remainder = n - even_bytes * 8;
for(std::size_t i = 0; i < even_bytes; ++i)
if(remainder)
reg |= (std::uint64_t)bytes[starting_byte + i] << (8 * (even_bytes - i));
else
reg |= (std::uint64_t)bytes[starting_byte + i] << (8 * (even_bytes - i - 1));
if(remainder)
reg |= (std::uint64_t)bytes[even_bytes];
// mask out anything before the first bit
if(pos % 8 != 0) {
std::size_t a = n - pos;
std::size_t b = n;
auto mask = bitfieldmask<std::uint64_t>(a, b);
reg = (reg & ~mask);
}
return reg;
}
最佳答案
我认为复制所有必要的字节然后屏蔽额外的位更简单:
std::uint64_t key_reg(std::uint8_t* bytes, std::size_t n)
{
std::uint64_t reg = 0;
std::reverse_copy( bytes, bytes + n / 8 + ( n % 8 != 0 ),
reinterpret_cast<char *>( ® ) );
reg >>= n % 8;
reg &= ~( -1UL << n );
return reg;
}
使用 pos
会稍微复杂一些:
std::uint64_t key_reg(std::uint8_t* bytes, std::size_t pos, std::size_t n)
{
std::uint64_t reg = 0;
auto endpos = pos + n;
auto start = bytes + pos / 8;
auto end = bytes + endpos / 8 + ( endpos % 8 != 0 );
std::reverse_copy( start, end, reinterpret_cast<char *>( ® ) );
reg >>= endpos % 8;
reg &= ~( -1UL << n );
return reg;
}
关于c++ - 将 n 位从 8 位数组复制到 64 位整数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48310288/