Effiziente Speichernutzung mit C-Bitfeldern
Angenommen, Ihr C-Programm enthält mehrere TRUE/FALSE-Variablen, gruppiert in einer Struktur namens status:
struct {
unsigned int widthValidated;
unsigned int heightValidated;
} status;
Diese Struktur benötigt 8 Bytes Speicher (2 × 4 Bytes für int), obwohl wir nur 0 oder 1 in jeder Variable speichern. C bietet eine bessere Möglichkeit, Speicher in solchen Situationen zu nutzen.
Wenn Sie solche Variablen in einer Struktur verwenden, können Sie die Breite einer Variablen definieren, was dem C-Compiler mitteilt, dass Sie nur diese Anzahl Bits benötigen. Die obige Struktur kann umgeschrieben werden als:
struct {
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;
} status;
Diese Struktur benötigt nun 4 Bytes für die status-Variable, aber nur 2 Bits werden für die Werte verwendet.
Wenn Sie bis zu 32 Variablen mit je 1 Bit Breite verwenden, belegt die Struktur immer noch 4 Bytes. Ab 33 Variablen wird der nächste Speicherslot allokiert (8 Bytes). Beispiel:
Beispiel: Speichervergleich
#include <stdio.h>
#include <string.h>
struct {
unsigned int widthValidated;
unsigned int heightValidated;
} status1;
struct {
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;
} status2;
int main() {
printf("Speicher status1 (normal): %zu Bytes\n", sizeof(status1));
printf("Speicher status2 (bit fields): %zu Bytes\n", sizeof(status2));
return 0;
}
Ausgabe:
Speicher status1 (normal): 8 Bytes
Speicher status2 (bit fields): 4 Bytes
Bit-Feld-Deklaration
Die Deklaration eines Bit-Feldes hat folgende Form innerhalb einer Struktur:
struct {
typ [mitgliedsname] : breite;
};
Beschreibung der Elemente:
| Nr. | Element & Beschreibung |
|---|---|
| 1 | typ – Ein ganzzahliger Typ, der bestimmt, wie der Bit-Feld-Wert interpretiert wird. Erlaubt: int, signed int, unsigned int. |
| 2 | mitgliedsname – Der Name des Bit-Feldes. |
| 3 | breite – Anzahl der Bits im Bit-Feld. Die Breite muss ≤ Bitbreite des spezifizierten Typs sein. |
Variablen mit vordefinierter Breite heißen Bit-Felder. Ein Bit-Feld kann mehr als ein einzelnes Bit halten; z. B. für Werte 0–7 benötigen Sie 3 Bits:
struct {
unsigned int age : 3;
} Age;
Dies weist den Compiler an, age nur 3 Bits zuzuweisen. Versucht man, einen Wert > 7 zu speichern, wird er abgeschnitten (Modulo 8).
Beispiel: Bit-Feld-Überlauf
#include <stdio.h>
#include <string.h>
struct {
unsigned int age : 3;
} Age;
int main() {
Age.age = 4;
printf("sizeof(Age): %zu\n", sizeof(Age));
printf("Age.age: %d\n", Age.age);
Age.age = 7;
printf("Age.age: %d\n", Age.age);
Age.age = 8; // Überlauf: 8 % 8 = 0
printf("Age.age: %d\n", Age.age);
return 0;
}
Ausgabe (mit Compiler-Warnung):
sizeof(Age): 4
Age.age: 4
Age.age: 7
Age.age: 0
Weitere Bit-Feld-Beispiele
struct {
unsigned int isReady : 1;
unsigned int isEnabled : 1;
unsigned int mode : 3; // 0-7
unsigned int priority : 4; // 0-15
unsigned int : 0; // Erzwingt Ausrichtung auf nächste Wortgrenze
unsigned int reserved : 8;
} flags;
Hinweis: Ein Bit-Feld der Breite 0 (:0) erzwingt die Ausrichtung auf die nächste Wortgrenze. Namelose Bit-Felder (ohne Mitgliedsnamen) können als Padding verwendet werden.
C Sprache
- C# Bitweise und Bit-Shift-Operatoren meistern: Umfassender Leitfaden
- Vier bewährte Muster für benutzerdefinierte Funktionen in C
- Arrays an Funktionen in C übergeben: 1D & 2D – Praxisleitfaden
- C-Structs und Zeiger meistern: Praxisleitfaden
- Java this-Schlüsselwort erklärt: Praktische Anwendungen, Konstruktoren und mehr
- Java-Kapselung meistern: Praktischer Leitfaden zum Datenverbergen
- C++ Structs erklärt mit praktischem Beispiel
- C-Funktionen meistern: Struktur, Deklaration & Best Practices
- Variable Argumente in C meistern: Ein praktischer Leitfaden
- MATLAB Integration meistern: Von Stammfunktionen zu Riemann-Summen