Zoeken…
Invoering
Bitvelden pakken C- en C ++ -structuren stevig samen om de grootte te verminderen. Dit lijkt pijnloos: geef het aantal bits voor leden op en de compiler doet het werk van het samenvoegen van bits. De beperking is het onvermogen om het adres van een bitveldlid te nemen, omdat het samen wordt opgeslagen. sizeof()
is ook niet toegestaan.
De kosten van bitvelden zijn tragere toegang, omdat geheugen moet worden opgehaald en bitgewijze bewerkingen moeten worden toegepast om lidwaarden te extraheren of te wijzigen. Deze bewerkingen dragen ook bij aan de uitvoerbare grootte.
Opmerkingen
Hoe duur zijn de bitsgewijze bewerkingen? Stel een eenvoudige veldstructuur zonder bit:
struct foo {
unsigned x;
unsigned y;
}
static struct foo my_var;
In enkele latere code:
my_var.y = 5;
Als sizeof (unsigned) == 4
, wordt x aan het begin van de structuur opgeslagen en wordt y 4 bytes in opgeslagen. De gegenereerde montagecode kan lijken op:
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
Dit is eenvoudig omdat x niet samengaat met y. Maar stel je voor dat je de structuur opnieuw definieert met bitvelden:
struct foo {
unsigned x : 4; /* Range 0-0x0f, or 0 through 15 */
unsigned y : 4;
}
Zowel x
als y
krijgen 4 bits toegewezen, die een enkele byte delen. De structuur neemt dus 1 byte in plaats van 8. Overweeg het samenstel om y
nu in te stellen, ervan uitgaande dat het in de bovenste nibbel terechtkomt:
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
Dit kan een goede afweging zijn als we duizenden of miljoenen van deze structuren hebben en het helpt het geheugen in de cache te houden of swapping te voorkomen - of kan het uitvoerbare bestand opzwellen om deze problemen en langzame verwerking te verergeren. Zoals met alle dingen, gebruik je gezond verstand.
Gebruik van apparaatstuurprogramma's : vermijd bitvelden als een slimme implementatiestrategie voor apparaatstuurprogramma's. Indelingen voor bitveldopslag zijn niet noodzakelijk consistent tussen de compilers, waardoor dergelijke implementaties niet-draagbaar zijn. Het lezen-wijzigen-schrijven om waarden in te stellen doet mogelijk niet wat apparaten verwachten en veroorzaakt onverwacht gedrag.
Verklaring en gebruik
struct FileAttributes
{
unsigned int ReadOnly: 1;
unsigned int Hidden: 1;
};
Hier zal elk van deze twee velden 1 bit in geheugen innemen. Het wordt gespecificeerd door : 1
uitdrukking achter de variabelenamen. Basistype van bitveld kan elk integraal type zijn (8-bit int tot 64-bit int). Het gebruik van unsigned
type wordt aanbevolen, anders kunnen er verrassingen komen.
Als meer bits vereist zijn, vervangt u "1" door het aantal vereiste bits. Bijvoorbeeld:
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
};
De hele structuur gebruikt slechts 22 bits en met normale compilerinstellingen zou de sizeof
deze structuur 4 bytes zijn.
Gebruik is vrij eenvoudig. Verklaar gewoon de variabele en gebruik deze als een gewone structuur.
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;