Hi Soul,
da du die Antwort mit dem "verodern" nicht verstehst, scheint es mir, als wenn du den Code oben nur benutzt hast ohne ihn zu verstehen!
Quelltext
1: 2: 3: 4:
| if ((zahl & 2) == 2) { Console.WriteLine("Global Group"); } |
okay ich fange am Besten mal von ganz vorne an. Das dauert jetzt zwar etwas, aber ich hoffe, dass dir hinterher klar ist, wie es funktioniert.
Zahlensystem
Du hast eine Speicherzellen, die 10 verschiedene Wertigkeiten annehmen kann 0,1,2,3,4,5,6,7,8,9. Damit kannst du in der Speicherzelle 10 verschiedene Zahlen darstellen.
Was ist jetzt aber, wenn du eine größere Zahl darstellen willst?
Du könntest entweder neue Ziffer/Wertigkeit erfinden oder eine zusätzliche Speicherzelle verwenden. Gewöhnlicherweise benutzt man zusäzliche Speicherzellen. Uns stehen jetzt also zwei Speicherzellen zur Verfügung die jeweils mit 10 verschiedenen Wertigkeiten belegt werden können. Somit stehen uns mit 2 Speicherzellen 10*10 = 100 verschiedene Belegungsmöglichkeiten zur Verfügung. Wir können also die Zahlen von 0 bis 99 (also 100 Stück) darstellen.
Der Computer macht das genauso, er hat nur nicht 10 Wertigkeiten, sondern nur 2 (0,1). Er kann also mit 2 Speicherzellen nur 4 verschiedene Zahlen darstellen.
Ein Integer z.B. ist eine Ansammlung von 32 Speicherzellen, die jeweils 0 oder 1 sein können. Das sind 2^32 verschiedene Zahlen, die ein Integer darstellen kann.
Flags
Trennt man sich jetzt von der Vorstellung das diese 32 Speicherzellen eine Zahl darstellen, könnte man einen Integer auch als eine Sammlung von 32 kleinen Schaltern bezeichnen, die jeweil an(1) oder aus(0) sein können. Vergleichbar mit einem bool[32]. Jeder Schalter hat dabei eine eigene unabhängige Aufgabe. Einen solchen kleinen Schalter nennt man Flag.
Oft gibt es in Frameworks Funktionen, die neben den Standard Paramtern als letzes eine Flag-Paramter haben.
Quelltext
1:
| int func1(float param1, string param2, int flag) |
Für gewöhnlich nimmt man dort die Zahl 0, was soviel wie standard bedeutet. Dieses Flag Parameter ist nichts anderes als eine Ansammlug von Speicherzellen, die 32 Schalter darstellen. Um zuverstehen, wie man diese Flag-Parameter setzen soll, muss man die Funktion der einzelnen Schalter wissen. Diese stehen meist in der Dokumentation.
z.B.
1. Schalter: param1 benutzen
2. Schalter: param2 benutzen
3. Schalter: kein Parameter benutzen
Man könnte natürlich auch 3 bool's in die Funktionskopfdeklaration stecken, das ist aber unschön, speicherverschwenden, ...
Damit man nicht immer in die Dokumentation schauen muss ist im den Header Datein der Funktion eine bestimmte Anzahl von Konstanten definiert
Quelltext
1: 2: 3: 4: 5:
| const byte func1_use_param1 = 1; const byte func1_use_param2 = 2; const byte func1_use_no_param = 4; ... = 8; ... = 16; |
Warum sind diese Konstanten nicht durchgängig nummeriert?
Das Geheimins liegt in ihrer Binärdarstellung aus 0 und 1. (siehe Zahlensystem oben)
Quelltext
1: 2: 3: 4: 5:
| const byte func1_use_param1 = 1 = 00000001; const byte func1_use_param2 = 2 = 00000010; const byte func1_use_no_param = 4 = 00000100; ... = 8 = 00001000; ... = 16 = 00010000; |
Diese Konstanten sind Ortsangaben für die entsprechenden Schalter.
func1_use_param2 heißt also, dass wenn man Parameter2 benutzen will, muss der dritte Schalter aktiviert sein.
Quelltext
1:
| func1(3.1f, "test", func1_use_param2) |
Was aber ist, wenn man mehrer Schalter anmachen möchte?
Jetzt kommen die binären Operatoren "and" und "or" ins Spiel.
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| 0 or 0 = 0 0 or 1 = 1 1 or 0 = 1 1 or 1 = 1
00000000 or 00000000 = 00000000 00000001 or 00000000 = 00000001 00000010 or 00000000 = 00000010 00000010 or 00000001 = 00000011
00000010 or 00000001 = 00000011 func1_use_param2 or func1_use_param1 = 00000011
func1_use_param2 or func1_use_param1 or func1_use_no_param = 00000111 |
Wenn man mehrere der genannten Konstanten "verodert", dann ergibt sich eine Zahl, die genau da 1'en hat, wo der entsprechende Schalter ist.
Man kann also durch das verodern 1'en setzen.
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| 0 and 0 = 0 0 and 1 = 0 1 and 0 = 0 1 and 1 = 1
11111111 and 00000000 = 00000000 11111111 and 00000010 = 00000010 01010101 and 00001111 = 00000101 01111111 and 10011001 = 00011001 |
Jetzt kommt dein Code von oben. Die Konstanten dienen bei AND als Maske. Verundet man eine Zahl mit einer solchen Maske, so wird das Ergebnis überall da 0'en haben, wo die Maske eine 0 hat. Und überall da wo die Maske eine 1 hat, wird der entsprechende Wert der Zahl stehen.
Die Funktion wird also intern über das Flag Parameter eine Maske legen und dann gucken, ob der entsprechende Schalter gedrückt wurde.
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| Flag And Mask = maskierte Flag
//Alle Schalter aktiviert flag = 11111111; //Maske für den dritten Schalter mask = 00000100;
if((flag and mask) = mask) { //hier war an der dritten stelle eine 1 }else{ //hier war an der dritten Stelle eine 0 } |
So ich hoffe, dass das ausführlich genug war um das mit den AND und OR und den Flags zu verstehen.
PS: Vielleicht kann nochmal wer anders rüber schauen, nicht das ich da irgendwo Quatsch geschrieben habe^^
Mit freundlichen Grüßen
Tobi