Suche…


Einführung

Bitfelder fassen C- und C ++ - Strukturen eng zusammen, um die Größe zu reduzieren. Dies erscheint mühelos: Geben Sie die Anzahl der Bits für die Member an, und der Compiler erledigt das Zusammenmischen von Bits. Die Einschränkung besteht darin, dass die Adresse eines Bitfeldmitglieds nicht übernommen werden kann, da sie gemischt gespeichert wird. sizeof() ist ebenfalls nicht zulässig.

Die Kosten für Bitfelder sind langsamer, da Speicher abgerufen und bitweise Operationen zum Extrahieren oder Ändern von Elementwerten ausgeführt werden müssen. Diese Vorgänge erhöhen auch die Größe der ausführbaren Datei.

Bemerkungen

Wie teuer sind die bitweisen Operationen? Angenommen, eine einfache Nicht-Bit-Feldstruktur:

struct foo {
    unsigned x;
    unsigned y;
}
static struct foo my_var;

In einem späteren Code:

my_var.y = 5;

Wenn sizeof (unsigned) == 4 , wird x am Anfang der Struktur gespeichert, und y wird 4 Byte in gespeichert. Der erzeugte Assembly-Code kann folgendermaßen aussehen:

loada register1,#myvar     ; get the address of the structure
storei register1[4],#0x05  ; put the value '5' at offset 4, e.g., set y=5

Dies ist einfach, weil x nicht mit y vermischt ist. Stellen Sie sich jedoch vor, Sie definieren die Struktur mit Bitfeldern neu:

struct foo {
    unsigned x : 4; /* Range 0-0x0f, or 0 through 15 */
    unsigned y : 4;
}

Sowohl x als auch y werden 4 Bits zugewiesen, die sich ein einzelnes Byte teilen. Die Struktur beansprucht somit 1 Byte statt 8. Betrachten Sie die Assembly jetzt mit y , sofern sie im oberen Halbbyte endet:

loada  register1,#myvar        ; get the address of the structure
loadb  register2,register1[0]  ; get the byte from memory
andb   register2,#0x0f         ; zero out y in the byte, leaving x alone
orb    register2,#0x50         ; put the 5 into the 'y' portion of the byte
stb    register1[0],register2  ; put the modified byte back into memory

Dies kann ein guter Kompromiss sein, wenn es Tausende oder Millionen solcher Strukturen gibt, und es hilft, den Arbeitsspeicher im Cache zu halten oder ein Auswechseln zu verhindern - oder die ausführbare Datei könnte aufgebläht werden, um diese Probleme zu verschlimmern und die Verarbeitung zu verlangsamen. Wie bei allen Dingen verwenden Sie ein gutes Urteilsvermögen.

Verwendung von Gerätetreibern: Vermeiden Sie Bitfelder als clevere Implementierungsstrategie für Gerätetreiber. Bitfeldspeicher-Layouts sind zwischen Compilern nicht notwendigerweise konsistent, sodass solche Implementierungen nicht portierbar sind. Die Werte zum Lesen, Ändern und Schreiben zum Setzen von Werten werden möglicherweise nicht den Anforderungen der Geräte entsprechen und verursachen unerwartetes Verhalten.

Erklärung und Verwendung

struct FileAttributes
{
    unsigned int ReadOnly: 1;    
    unsigned int Hidden: 1;
};

Hier belegt jedes dieser beiden Felder 1 Bit im Speicher. Es wird angegeben durch : 1 Ausdruck hinter den Variablennamen. Der Basistyp des Bitfelds kann ein beliebiger integraler Typ sein (8-Bit-Int. Bis 64-Bit-Int). Die Verwendung eines unsigned Typs wird empfohlen. Andernfalls können Überraschungen auftreten.

Wenn mehr Bits erforderlich sind, ersetzen Sie "1" durch die Anzahl der erforderlichen Bits. Zum Beispiel:

struct Date
{
    unsigned int Year : 13; // 2^13 = 8192, enough for "year" representation for long time
    unsigned int Month: 4;  // 2^4 = 16, enough to represent 1-12 month values.
    unsigned int Day:   5;  // 32
};

Die gesamte Struktur verwendet nur 22 Bit. Bei normalen Compilereinstellungen wäre die sizeof dieser Struktur 4 Byte.

Die Nutzung ist ziemlich einfach. Deklarieren Sie einfach die Variable und verwenden Sie sie wie eine gewöhnliche Struktur.

Date d;

d.Year = 2016;
d.Month = 7;
d.Day =  22;

std::cout << "Year:" << d.Year << std::endl <<
        "Month:" << d.Month << std::endl <<
        "Day:" << d.Day << std::endl;


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow