Nochwas ist mir aufgefallen.
Wenn es um die Angabe eines Bits in einem Bitfeld -> Integer/Cardinal usw. geht sollte man deren Index IMMER 0-basiert angeben.
Also, ein byte besteht aus 8 Bits mit den Indizes 0 bis 7. Das unterste Bit in desem Byte hat also Index 0 unddas höchstwertige Bit hat 7.
Desweiteren stellt man eine binärzahl immer von Rechts nach Links dar. Die Zahl $85 = 133 = 10000101b. D.h. die Bitindizes dieser Zahl im Binärdarstellungen sind so:
Warum ? weil
10000101 = 133 = (1 * 2^
7) or (1 * 2^
2) or (1*2^
0)
ist. Man sieht also das der Bit Index (0 bis 7) identisch zur Bit-Wertigkeit -> 2^BitIndex ist. Diese beiden Regeln vereinfachen die komplete Denklogik.
Zudem ist es per Definition einfach falsch das das niederwertigste Bit in einem Byte das Bit mit Index 1 ist. Es gibt ganz klare mathematische Definitionen das man mit dem Index 0 beginnt.
Auch schreibt man immer von "Rechts nach Links" zahlen, selbst unsere Dezimalzahlen werden zB. 133 statt 331 geschrieben, also ist 8 -> 1000 binär und nicht 0001.
Warum man nun Bitmengen -> Boolsche Mengen benutzt ?
Ganz enfach weil die zB. Menge "Farben" auch nur aus den Elementen "Rot", "Grün", "Blau" besteht.
Und Bitcodiert Flags eben eine Menge aus verscheiden Flags darstellen. Der Zahlenwert einer solchen Bitkonstante bestimmt im Grunde deren vorher schon ausgerechneten Wertigkeit des Bits.
Also angenommen wir haben eine Flag-Menge mit
Delphi-Quellcode:
const
Rot = 0;
Grün = 1;
Blau = 2;
var
Flag: Byte -> (Rot, Grün, Blau)
Die Konstanten für Rot, Grün, Blau stellen die Mengen-Wertigkeit dar. Da diese Mengen-Wertigkeit in einem Flag vom Typ Byte gespeichert werden sollen, sind die Mengen-Wertigkeiten identisch zur den Bit-Indizes. Also:
Delphi-Quellcode:
Flags := 2^Rot or 2^Grün or 2^Blau; // Flags enthält nun Rot + Grün + Blau
-> oder eben
Flags := (1 shl Rot) or (1 shl Grün) or (1 shl Blau)
-> predefiniert um das shl zu sparen also
const
Rot = 1 shl 0; // Bit an Index 0 == 2^0 == 1
Grün = 1 shl 1; // Bit an Index 1 == 2^1 == 2
Blau = 1 shl 2; // Bit an Index 2 == 2^2 == 4
Gelb = 1 shl 3; // Bit an Index 3 == 2^3 == 8
Grau = 1 shl 4; // Bit an Index 4 == 2^4 == 16
D.h. im Windows
API hat der Programmierer die Bitwertigkeit eines Flags schon im vorhinein ausgerechnet und als Zahl dargestellt. In Wirklichkeit sind es aber KEINE Zahlen sondern Mengen-Elemente.
Nun, die Kombination und Rekombination von Mengen-Elemente dürfen NICHT dazu führen das sich die Kardinalität der Menge verändert !!
Beispiel:
Delphi-Quellcode:
Farbe := Rot or Grün;
// alles Korrekt, da Farbe Rot und Grün enthält
Farbe := Farbe or Blau;
// immer noch alles korrekt
Farbe := Farbe + Rot;
// FALSCH !! Farbe war voeher 0111b nun aber 1000b
// Farbe müsste aber immer noch Rot,Grün,Blau sein ist es aber nicht denn sie ist Gelb = 2^3 = 8.
// richtig wäre also
Farbe := Farbe or Rot;
Im obigen Beispiel wurde also die Operation + in einer Bitcodierten Menge angewednet und diese führte zu Fehlern.
Nun aber man weg vom C++
API Shit hin zu dem Weg wie man es in einer richtige Programmiersprache machen sollte. Ich schlage mal als richtige Programmiersprache die Sprache PASCAL vor, also Delphi:
Delphi-Quellcode:
type
Farben = (rot, grün, blau, gelb, grau];
Farbe = set of Farben;
var
Flag: Farbe;
begin
Flag := [rot grün];
Flag := Flag + blau;
Flag := Flag + rot;
ShowMessage( IntToBin( Byte( Flag ) ) );
end;
Wie du siehst bei Mengen, die intern auch nur Bitcodiert gespeichert werden, wird eine gute Sprache auch die in der Mathematik üblichen Operationen +,-,* der Mengenlehre benutzen.
Wenn du also auf diese Operatoren bestehen willst dann benutze auch die Typdeklarationen zur Deklatration von Mengen.
Auf reiner Computer Ebene sind nämlich die Mengenoperation "+" identisch mit der Bitoperation OR, die Operation "-" mit der Operation AND NOT, die Operation "*" mit der Operation AND.
Gruß Hagen