example ejemplos c++ c arrays struct bit-fields

c++ - ejemplos - ¿Es posible utilizar una matriz de campos de bits?



bitset c++ example (3)

Tengo curiosidad por saber, ¿Es posible utilizar una matriz de campos de bits? Me gusta:

struct st { unsigned int i[5]: 4; };


C no admite matrices de campos de bits, por lo que la respuesta corta es no.

Para matrices muy grandes, podría valer la pena empaquetar valores, 2 por byte, de esta manera:

#define ARRAY_SIZE 1000000 unsigned char arr[(ARRAY_SIZE + 1) / 2]; int get_4bits(const unsigned char *arr, size_t index) { return arr[index >> 1] >> ((index & 1) << 2); } int set_4bits(unsigned char *arr, size_t index, int value) { arr[index >> 1] &= ~ 0x0F << ((index & 1) << 2); arr[index >> 1] |= (value & 0x0F) << ((index & 1) << 2); }


No, no puedes. El campo de bits solo se puede utilizar con variables de tipo integral.

C11-§6.7.2.1 / 5

Un campo de bits debe tener un tipo que sea una versión calificada o no calificada de _Bool , signed int , unsigned int o algún otro tipo definido por la implementación.

Alternativamente puedes hacer esto

struct st { unsigned int i: 4; } arr_st[5];

pero su tamaño será 5 veces el tamaño de una struct (como se menciona en el comment de @ Jonathan Leffler ) con 5 miembros cada uno con el campo de bits 4 . Por lo tanto, no tiene mucho sentido aquí.

Más de cerca puedes hacer esto

struct st { uint8_t i: 4; // Will take only a byte } arr_st[5];


Puedes escribir tu propia clase para este caso. Por ejemplo:

template <typename T, size_t ITEM_BIT_SIZE> class BitArrayView { private: static const size_t ARRAY_ENTRY_BITS = sizeof(T) * 8; static const T ITEM_MASK = (~((T) 0)) >> (ARRAY_ENTRY_BITS - ITEM_BIT_SIZE); T* arr; public: struct ItemMutator { BitArrayView* owner; size_t index; T operator=(T value) { return owner->set(index, value); } operator T() { return owner->get(index); } }; const size_t bitSize; BitArrayView(T* arr, size_t length) : arr(arr), bitSize((length * ARRAY_ENTRY_BITS) / ITEM_BIT_SIZE) {} T get(size_t index) const { size_t bitPos = index * ITEM_BIT_SIZE; size_t arrIndex = bitPos / ARRAY_ENTRY_BITS; size_t shiftCount = bitPos % ARRAY_ENTRY_BITS; return (arr[arrIndex] >> shiftCount) & ITEM_MASK; } T set(size_t index, T value) { size_t bitPos = index * ITEM_BIT_SIZE; size_t arrIndex = bitPos / ARRAY_ENTRY_BITS; size_t shiftCount = bitPos % ARRAY_ENTRY_BITS; value &= ITEM_MASK; // trim arr[arrIndex] &= ~(ITEM_MASK << shiftCount); // clear target bits arr[arrIndex] |= value << shiftCount; // insert new bits return value; } ItemMutator operator[](size_t index) { return { this, index }; } };

Y luego puedes acceder a él como una matriz de "campo de bits":

// create array of some uints unsigned int arr[5] = { 0, 0, 0, 0, 0 }; // set BitArrayView of 3-bit entries on some part of the array // (two indexes starting at 1) BitArrayView<unsigned int, 3> arrView(arr + 1, 2); // should equal 21 now => (2 * 32) / 3 arrView.bitSize == 21; for (unsigned int i = 0; i < arrView.bitSize; i++) { arrView[i] = 7; // eg.: 0b111; } // now arr[1] should have all bits set // and arr[2] should have all bits set but last one unset => (2 * 32) % 3 = 1 // the remaining arr items should stay untouched

Esta es una implementación simple que debería funcionar solo con matrices de respaldo sin firma.

Observe "el truco del mutador" en el operator[] ;).

Por supuesto, también se podrían implementar otros operadores.