Простой подход состоит в том, чтобы иметь «текущий байт» (acc
в следующем), соответствующее количество используемых битов в нем (bitcount
) и вектор полностью обработанных байтов (output
):
int acc = 0;
int bitcount = 0;
std::vector<unsigned char> output;
void writeBits(int size, unsigned long long x)
{
while (size > 0)
{
// sz = How many bit we're about to copy
int sz = size;
// max avail space in acc
if (sz > 8 - bitcount) sz = 8 - bitcount;
// get the bits
acc |= ((x >> (size - sz)) << (8 - bitcount - sz));
// zero them off in x
x &= (1 << (size - sz)) - 1;
// acc got bigger and x got smaller
bitcount += sz;
size -= sz;
if (bitcount == 8)
{
// got a full byte!
output.push_back(acc);
acc = bitcount = 0;
}
}
}
void writeNumber(unsigned long long x)
{
// How big is it?
int size = 0;
while (size < 64 && x >= (1ULL << size))
size++;
writeBits(size, x);
}
Обратите внимание, что в конце обработки вы должны проверить, есть ли еще бит в аккумуляторе (bitcount > 0
), и вы должны сбросить их в этом случае, выполнив output.push_back(acc);
.
Обратите также внимание, что если скорость является проблемой, то, вероятно, хорошей идеей является использование большего аккумулятора (однако выход будет зависеть от порядкового номера машины), а также то, что определение количества битов, используемых в числе, может быть сделано намного быстрее, чемлинейный поиск в C ++ (например, x86 имеет специальную инструкцию машинного языка BSR
, предназначенную для этого).