2010-09-04 11 views
8

Kürzlich bin ich auf einige Beispiele von "Flags" in C und C++ gestoßen, und ich verstehe nicht ganz, wie sie funktionieren. irgend Quellcode Nach einem Blick bemerkte ich, dass oft Flagwerten in hexadezimal definiert sind wie die folgenden:Wie funktionieren Flags in C?

FLAG1 = 0x00000001, 
FLAG2 = 0x00000010, 

Meine intuitive lässt vermuten, dass diese Werte kombiniert werden. Funktionieren Flags, indem alle Flag-Werte zu einem Int kombiniert werden? Wenn ich beide wie FLAG1 | FLAG2 verwendet hätte, wäre das Ergebnis 0x00000011?

Muss ich Aufzählungen mit Bitversatze erstellen oder kann ich aufsteigend ganze Zahlen wie:

FLAG1 = 1; 
FLAG2 = 2; 

Antwort

20

Sie müssen die Bits versetzen, sonst gibt es keine Möglichkeit, die einzelnen Flags zu extrahieren. Wenn Sie Flags haben, die 1, 2, 3, & 4 und einen kombinierten Wert von 5 entsprechen, wie können Sie dann feststellen, ob es sich um 2 & 3 oder 1 & 4 handelt?

Sie können es auch tun, auf diese Weise, zum Beispiel:

enum { 
    FIRST = 1 << 0, // same as 1 
    SECOND = 1 << 1, // same as 2, binary 10 
    THIRD = 1 << 2, // same as 4, binary 100 
    FOURTH = 1 << 3 // same as 8, binary 1000 
}; 

Dann kombinieren Sie Flags wie so:

int flags = FIRST | THIRD | FOURTH; 

Und Sie extrahieren sie wie folgt aus:

if (flags & THIRD) { ... 
+0

Vielen Dank das ist sehr einfach, Sie gewinnen. –

+3

* Sie gewinnen * - Wirklich? Wenn eine gute Antwort gepostet wird, würde ich sagen, dass ** jeder ** gewinnt. Und ich * wirklich * hoffe, dass FIRST, SECOND usw. nur schlechte Beispielsnamen sind und kein Vorschlag, diese konstant zu deklarieren und sie wiederzuverwenden. 'x = ZWEITE | FOURTH' ist nicht so lesbar wie 'x = TEXTUREFLAGS_POINTSAMPLE | TEXTUREFLAGS_TRILINEAR'. –

+1

"Sie gewinnen" wie in "Danke" "große Antwort," ich akzeptiere deins. "Ich denke, die Namensgebung wurde angedeutet. –

6

Ihre erste Methode ist, um die Bits auf die effizienteste Art und Weise nicht verwenden. Im ersten Beispiel verwenden Sie hexadezimale Notation und es ist äquivalent zu:

TEXTUREFLAGS_POINTSAMPLE = 1, 
TEXTUREFLAGS_TRILINEAR = 16, 

Bei der zweiten Methode scheint es, dass Sie nur von jeweils einer Zeit erhöht werden. Dies funktioniert nicht, wenn Sie Flags kombinieren, da der kombinierte Wert dasselbe wie ein anderes Flag sein kann (z. B. 1 | 2 == 3).

Sie sollten diese Werte verwenden, statt:

0x00000001 // == 1 
0x00000002 // == 2 
0x00000004 // == 4 
0x00000008 // == 8 
0x00000010 // == 16 
0x00000020 // == 32 
0x00000040 // == 64 
etc... 

Dies sind die Zweierpotenzen und können sie kombiniert werden mit bitweise oder in irgendeiner Weise ohne Kollisionen zu geben.

+0

Ok, aber es wird nicht funktionieren, wenn ich nur eins mache, um 20 zu mögen? Ich muss immer noch das Hexadezimal taumeln, damit sie sich nicht gegenseitig überschreiben, oder? Oder verstehe ich nicht, wie es funktioniert. –

+1

@ user425756, wenn Sie keine Zweierpotenzen verwenden, können Sie nicht den Unterschied zwischen der 1 und der 2, die gesetzt wird, unterscheiden, oder 3 wird gesetzt. –

+0

Ja das ist, was ich dachte. –

4

Flags wie dieses sind binäre Werte, so dass Sie 1, 2, 4, 8, 16, 32, 64, 128 in einem einzigen Byte oder weitere Potenzen von 2 bis 2^31 i kombinieren können n an int. Da es sich um binäre Werte handelt, können Sie sie zusammen "or", also, wenn Sie "oder" zusammen 1,2,4, enden Sie zum Beispiel mit 7. Und Sie können das gewünschte Bit mit "und" extrahieren - wenn Sie also einen int mit einigen Flags oder zusammen haben und sehen wollen, ob das "4" Bit gesetzt ist, können Sie if (flag & 4) sagen und es wird wahr sein wenn das Bit "4" gesetzt ist.

+0

Vielen Dank, dass macht mehr Sinn. –

2

man denke an die Fahnen als ein Array von 32 Bit (booleans)

eines dieser Bits auf Sie aktivieren oder mit 1 < < BitIndex (wo BitIndex Null-basiert, so dass 0-31) So schalten Sie einen los und es mit ~ (1 < < BitIndex) Um zu überprüfen, ob es ein oder aus Ihnen und es mit (1 < < BitIndex)

Sobald Sie über die Differenz erhalten zwischen digitalen OR/AND gegen logische ODER/UND es wird alles klicken. Dann werden Sie die hexadezimale Schreibweise zu schätzen wissen!