Använda uppräknade typer som bitflaggor (1 / 3 steg)
Steg 1: bakgrund
Till exempel kunde vi förklara ett 8-bitars heltal som en flagga att visa några instruktioner eller inte eller inte:
unsigned char DISPLAY_INSTRUCTIONS = 1;
Med en 8-bitars värde skulle tillåta oss att ha 28 möjliga värden eller 256 unika flaggor. Varje flagga skulle ta upp en byte av resurser, antingen på disken eller i core RAM. Vi kan också använda andra värden för standardmassa för flaggan som uint16_t, ett 16-bitarsvärde som lagrar upp till 65 535 unika flaggor, förmodligen mycket mer än vi kunde behöver eller någonsin använda. Men vad händer om vi bara hade, säger, 6 flaggor vi behövs för att spåra? I ovanstående system skulle det kräva sex byte, en byte för varje flagga, men använder bitflaggor kunde vi förvara alla sex flaggor (och lite) inuti en enda byte.
Om du är obekant med binära tal, kan du ta en stund och läsa min instructable på antalet baser, som innehåller binära eller hitta ett antal Självstudiekurser online. Jag antar du redan har ett passerande förståelse av hur binära tal sätts samman. Så, kanske du frågar hur använder man de enskilda bitarna inuti ett heltal som en flagga för användning i koden/programvara? Vanligtvis, detta görs genom att tilldela lite till "1" eller "0" och utifrån sin placering inuti heltalet, kan användas för en bekräftelse eller en negation av det angivna värdet. Till exempel, ta en 8-bitars nummer, säger noll och titta på den.
0000 0000
OK, inget spännande här. Den 1 läge, gör det nu 1:
0000 0000
Vi kan göra samma sak för de två plats:
0000 0010
eller de fyra plats:
0000 0100
eller kanske 32 och 8: e plats:0010 1000
Vilka siffror gör dessa lite volter? Vi bryr oss inte. Vi är bara bekymrad över de enskilda bitarna inuti numret i detta fall. För att enkelt tilldela flaggvärden till bitar, är det vanligt att använda följande idiomet:
#define FLAG1 0x01 // 0000 0001
#define FLAG2 0x02 // #define FLAG1 0x01 // 0000 0001
#define FLAG2 0x02 // 0000 0010
#define FLAG3 0x04 // 0000 0100
#define FLAG4 0x08 // 0000 1000
#define FLAG5 0x10 // 0001 0000
#define FLAG6 0x20 // 0010 0000
#define FLAG7 0x40 // 0100 0000
#define FLAG8 0x80 // 1000 0000
#define FLAG3 0x04 // unsigned char myFlags = 0x00; myFlags |= FLAG5;
#define FLAG4 0x08 // 0000 1000
#define FLAG5 0x10 // 0001 0000
#define FLAG6 0x20 // 0010 0000
#define FLAG7 0x40 // 0100 0000
#define FLAG8 0x80 // 1000 0000
Det har vi gjort våra flaggor. Ta del av mönstret i både det hexadecimala tal och dess binär representation. Så, om FLAG5 är, sedan integer flaggan skulle har lite 5 set (med hjälp av en 1-baserat index, tvärtemot den mer gemensamma 0-baserat, men det är inte viktigt för oss just nu). Att skapa variabeln flagga och ange FLAG5 ser ut så här:
myFlags &= ~FLAG3;
Vi eller flaggor så att några befintliga flaggor kommer att förbli bevarade. Om du och flaggor, du kommer att skriva över alla befintliga flaggor med bitmask din ANDing det till. Detta är användbart när du vill ta bort en flagga:
#define FLAG28 0x00400000
De ovanstående uppsättningarna FLAG3 till noll. Märke att du är ANDing med ett komplement av flaggan.
Men vad händer om du har:
#define FLAG_1 0x01
#define FLAG_2 0x02
#define FLAG_3 0x04
#define FLAG_4 0x08
...
uint32_t _flags;
// set a flag
_flags |= FLAG_2;
// clear a flag
_flags &= ~FLAG_3;
// test bit flag
if (_flags & FLAG_4)
do_something();
och du försöker ställa in det med vår 8-bitars heltal? Du har ett överflöd med inkompatibla heltal storlekar och får ett fel, troligen vid körning och inte kompilera tid eftersom kompilatorn kommer vanligtvis främja eller annars implicit konvertera din konstant flagga till den typ som fungeras på. Detta inte alltid fallet, men det är ofta. Detta kan skapa svårt att fånga buggar och den värsta sorten: runtime fel. De är dåligt eftersom de kan vara svårare att spåra, svårare för att replikera, och introducerade till din användare, du vill aldrig göra om möjligt.
Vidare, vad om du behövde en ny flagga, säga FLAG9 men med värdet 0x0080 av någon anledning? Skulle du behöva 1) förlänga din flagga Skriv för att rymma den större storleken och 2) infoga flaggan i din flagga deklarationer och numrera om alla flaggor bakom den. Det är helt enkelt inte genomförbart och definitivt inte underhållas.
Vad gör du om dessa problem? Hur kan vi garantera typsäkerhet och utbyggbarhet till våra flaggor? Vända blad och få reda på!