Pergunta

Eu tenho um unsigned char tampão, e eu estou querendo saber como eu iria escrever e ler os bits assinados e não assinados a este buffer de bytes.

No Source Engine existe uma classe chamada bf_write , que dois métodos principais (usado por WriteString, WriteChar, WriteLong, etc.) o uso duas funções chamado WriteUBitLong e WriteSBitLong .

Agradecemos antecipadamente

Foi útil?

Solução

Se o número de bits é uma constante de tempo de compilação:

#include <bitset>
...
std::bitset<100> b;
b[2]=true;

Se não for, o uso Boost.dynamic_bitset

Ou, se você está desesperado, std :: vector, que é de fato um vetor pouco embalado:

#include <vector>
...
std::vector<bool> b(100);
b[2]=true;

Você parece querer usar uma biblioteca que exige vetores bit embalados em uma matriz de bytes. Sem saber exatamente o que pedir ele coloca os bits em, só posso notar que:

1) todos os acima provavelmente irá utilizar pelo menos ints de 32 bits com os bits ordenada menos-> mais ou mais-> menos significativo

2) em little endian (Intel / AMD) CPUs, isso significa que a memória ocupada pelo bytes um array de inteiros pode não ser consistente com a ordem dos bits dentro do int. se é "bit 0 é o LSB de int 0, ... Bit 32 é o LSB de int 1, ...", então isso é o mesmo em little endian como "bit 0 é o LSB do caractere 0, ... bit 32 é o LSB de Char 4 ... ", caso em que você pode simplesmente lançar um ponteiro para a matriz int para um ponteiro para matriz de char

3) supondo que a ordem natural de bytes em seu conjunto de bits / vetor não é exatamente o que as necessidades da biblioteca, então você tem que quer ter de criar o seu próprio que tem o layout que eles querem, ou transcrever uma cópia em seu layout .

a) se a ordem dos bits dentro de um byte é diferente, uma pesquisa de tabela 256 de entrada dando a byte com pedaços invertidos seria eficiente. você poderia gerar a tabela com uma pequena rotina.

b) para inverter bytes de pouco <-> big endian:

inline void endian_swap(unsigned short& x)
{
    x = (x>>8) | 
        (x<<8);
}

inline void endian_swap(unsigned int& x)
{
    x = (x>>24) | 
        ((x<<8) & 0x00FF0000) |
        ((x>>8) & 0x0000FF00) |
        (x<<24);
}    

inline void endian_swap(unsigned long long& x)
{
    x = (x>>56) | 
        ((x<<40) & 0x00FF000000000000) |
        ((x<<24) & 0x0000FF0000000000) |
        ((x<<8)  & 0x000000FF00000000) |
        ((x>>8)  & 0x00000000FF000000) |
        ((x>>24) & 0x0000000000FF0000) |
        ((x>>40) & 0x000000000000FF00) |
        (x<<56);
}

Para obter / definir um pouco particular dentro de uma palavra, com pouco # 0 no bit menos significativo da palavra 0:

typedef unsigned char block_t;
const unsigned block_bits=8;

inline void set_bit(block_t *d,unsigned i) {
  unsigned b=i/block_bits;
  unsigned bit=i-(block_bits*b); // same as i%b
  block_t &bl=d[b];
  bl|=(1<<bit); // or bit with 1 (others anded w/ 0)
}

inline void clear_bit(block_t *d,unsigned i) {
  unsigned b=i/block_bits;
  unsigned bit=i-(block_bits*b); // same as i%b
  block_t &bl=d[b];
  bl&=(~(1<<bit)); // and bit with 0 (other bits anded w/ 1)
}

inline void modify_bit(block_t *d,unsigned i,bool val) {
  if (val) set_bit(d,i) else clear_bit(d,i);
}

inline bool get_bit(block_t const* d,unsigned i) {
  unsigned b=i/block_bits;
  unsigned bit=i-(block_bits*b); // same as i%b
  return d[b]&(1<<bit);
}

Obviamente, se a regra para difere organização pouco, você tem que mudar o acima.

Usando o mais vasto int possível seus processos CPU eficientemente quanto block_t é melhor ( 'Não se esqueça de mudança block_bits), a menos que o endianness não funciona w / a biblioteca que você está usando.

Outras dicas

Eu acho que algumas macros são suficientes:

#define set_bit0(buf, i) ((buf)[(i)/8]&=~(1u<<(i)%8))
#define set_bit1(buf, i) ((buf)[(i)/8]|=1<<(i)%8)
#define get_bit(buf, i) ((buf)[(i)/8]>>(i)%8&1)

Além disso, trocando endianness pode ser feito de forma mais rápida. Por exemplo, para um número inteiro v 64-bit, as seguintes operações de swap a sua ordenação:

v = ((v & 0x00000000FFFFFFFFLLU) << 32) | (v >> 32);
v = ((v & 0x0000FFFF0000FFFFLLU) << 16) | ((v & 0xFFFF0000FFFF0000LLU) >> 16);
v = ((v & 0x00FF00FF00FF00FFLLU) << 8) | ((v & 0xFF00FF00FF00FF00LLU) >> 8);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top