Ich bin neugierig zu wissen, Ist es möglich, ein Array von Bitfeldern zu verwenden? Wie:
struct st
{
unsigned int i[5]: 4;
};
msc
Ich bin neugierig zu wissen, Ist es möglich, ein Array von Bitfeldern zu verwenden? Wie:
struct st
{
unsigned int i[5]: 4;
};
hackt
Nein, das kannst du nicht. Das Bitfeld kann nur mit Variablen vom Typ Integral verwendet werden.
Ein Bitfeld muss einen Typ haben, der eine qualifizierte oder nicht qualifizierte Version davon ist
_Bool
,signed int
,unsigned int
oder einen anderen implementierungsdefinierten Typ.
Alternativ können Sie dies tun
struct st
{
unsigned int i: 4;
} arr_st[5];
aber seine Größe wird fünfmal so groß sein wie a struct
(wie im Kommentar von @Jonathan Leffler erwähnt) mit jeweils 5 Mitgliedern mit Bitfeld 4
. Hier macht es also wenig Sinn.
Genauer können Sie dies tun
struct st
{
uint8_t i: 4; // Will take only a byte
} arr_st[5];
Aber die Größe davon (struct st { unsigned int i: 4; } arr_st[5];
wäre höchstwahrscheinlich 5 mal so groß wie ein unsigned int
; es wäre nicht 20 Bit lang.
– Jonathan Leffler
29. Januar 2017 um 7:10 Uhr
@JonathanLeffler; Ja. Aber keine anderen Möglichkeiten, ein Array von Bitfeldern zu deklarieren.
– Hacken
29. Januar 2017 um 7:22 Uhr
@hackks Danke, dass du mir geholfen hast.
– msc
29. Januar 2017 um 7:55 Uhr
Typ uint8_t
möglicherweise nicht verfügbar. struct st { unsigned char i: 4; } arr_st[5];
oder nur unsigned char arr[5];
scheinen vorzuziehen.
– chqrlie
29. Januar 2017 um 8:13 Uhr
@IlmariKaronen; Ich meine struct arr_st
wird sein 5
mal struct like struct stt { unsigned int i: 4; unsigned int j: 4; unsigned int k: 4; unsigned int l: 4; unsigned int m: 4; } s;
– Hacken
29. Januar 2017 um 13:53 Uhr
chqrlie
C unterstützt keine Arrays von Bitfeldern, daher lautet die kurze Antwort nein.
Bei sehr großen Arrays kann es sich lohnen, Werte zu packen, 2 pro Byte, auf diese Weise:
#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);
}
Tomasz Gawel
Sie können für diesen Fall Ihre eigene Klasse schreiben. Zum Beispiel:
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 };
}
};
Und dann können Sie wie auf ein “Bitfeld” -Array zugreifen:
// 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
Dies ist eine einfache Implementierung, die nur mit nicht signierten Sicherungsarrays funktionieren sollte.
Beachten Sie den „Mutator-Trick“ in operator[]
;).
Natürlich könnten auch einige andere Operatoren implementiert werden.
Beachten Sie das am meisten jüngste C-Code verwendet keine Bitfelder mehr. Eine nützliche Alternative wäre die Verwendung von Bitmaskenfeldern und die Durchführung bitweiser Operationen an ihnen. Übrigens generiert der Compiler äquivalenten Code.
– Basile Starynkevitch
29. Januar 2017 um 7:39 Uhr
@BasileStarynkevitch: Ich frage mich, woher Sie das ableiten. Die Verwendung von Bitfeldern ist viel weniger fehleranfällig als die Behandlung von Bitmaskenfeldern mit bitweisen Operationen.
– chqrlie
4. Februar 2017 um 22:22 Uhr