Domanda

Ho un buffer carattere senza segno e mi chiedo come scrivere e leggere i bit con e senza segno su questo buffer di byte.

Nel motore di origine esiste una classe denominata bf_write , che due metodi principali (utilizzati da WriteString, WriteChar, WriteLong, ecc.) utilizzano due funzioni denominate WriteUBitLong e WriteSBitLong .

Grazie in anticipo

È stato utile?

Soluzione

Se il numero di bit è una costante di compilazione:

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

In caso contrario, utilizzare Boost.dynamic_bitset

Oppure, se sei disperato, std :: vector, che in effetti è un bit pack impacchettato:

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

Sembra che tu voglia usare una libreria che richiede vettori di bit impacchettati in una matrice di byte. Senza sapere esattamente in quale ordine inserisce i bit, posso solo notare che:

1) tutto quanto sopra probabilmente utilizzerà almeno 32 bit ints con bit ordinati almeno - > most o most - > meno significativo

2) su CPU little endian (Intel / AMD), ciò significa che la memoria occupata dai byte una matrice di in potrebbe non essere coerente con l'ordinamento dei bit all'interno di int. se è " bit 0 è lsb di int 0, ... bit 32 è lsb di int 1, ... " allora è lo stesso in little endian di " bit 0 è lsb di char 0, ... bit 32 è lsb di char 4 ... " ;, nel qual caso puoi semplicemente lanciare un puntatore alla matrice int su un puntatore alla matrice di caratteri

3) supponendo che l'ordine nativo di byte nel tuo set di bit / vettore non sia esattamente ciò di cui la libreria ha bisogno, quindi devi creare il tuo che ha il layout che desidera o trascriverne una copia nel suo layout .

a) se l'ordine dei bit all'interno di un byte è diverso, una tabella di ricerca a 256 voci che fornisce il byte con bit invertiti sarebbe efficace. potresti generare la tabella con una piccola routine.

b) per invertire i byte dal piccolo < - > 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);
}

Per ottenere / impostare un determinato bit all'interno di una parola, con il bit # 0 nel bit meno significativo della parola 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);
}

Ovviamente se la regola per l'organizzazione dei bit è diversa, è necessario modificare quanto sopra.

Usando il più ampio possibile int la tua CPU elabora in modo efficiente come block_t è meglio (non dimenticare di cambiare block_bits), a meno che l'endianness non si risolva con la libreria che stai usando.

Altri suggerimenti

Penso che siano sufficienti alcune macro:

#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)

Inoltre, lo scambio di endianness può essere fatto in modo più rapido. Ad esempio, per un numero intero a 64 bit v, le seguenti operazioni scambiano la sua endianness:

v = ((v & 0x00000000FFFFFFFFLLU) << 32) | (v >> 32);
v = ((v & 0x0000FFFF0000FFFFLLU) << 16) | ((v & 0xFFFF0000FFFF0000LLU) >> 16);
v = ((v & 0x00FF00FF00FF00FFLLU) << 8) | ((v & 0xFF00FF00FF00FF00LLU) >> 8);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top