Zitat von
sonicfire:
Danke! Aber wieso ein "or" dazwischen? Nicht: fmOpenRead, fmSowieso?
Also, fmSowieso ist eigentlich nur eine Konstante Zahl. Diese hat aber eine besondere Eigenschaft, die du von den Delphi-Sets kennen kannst, ansonsten spricht man auch gerne von Bitfeldern. Wenn du ein Integer nimmst, hast du 32 Bit. Du kannst also theoretisch (auch praktisch) jedes einzelne Bit setzen oder eben nicht. Damit kannst du in einem Integer 32 Zustände speichern (die allerdings auch sehr einfach sind). Es ist halt wirklich ein Boolscher Wert (Bit = 1 oder nicht = 0).
Anschaulicher ist das ganze, wenn wir jetzt mal nur zwei Zustände z1 und z2 betrachten die auch nur in einem Byte kodiert werden (die anderen führenden 24 0en eines Integers lasse ich nur fauler Weise weg!).
In der binären Darstellung entspricht so eine Bit einer 2er Potenz. Das niederwertigste Bit entspricht 2^0 = 1, dass nächste 2^1 = 2, es kämen 2^2 = 4, 2^3 = 8, ...
Das n-te Bit ist also gerade 2^n (wobei man hier wieder sieht warum man so gerne mit der null beginnt).
Wenn du jetzt Zustände in Bits kodieren möchtest, solltest du ihnen jeweils ein eigenes Bit zuweisen (sonst kannst du schließlich die Zustände nicht unterscheiden). Dazu weißt du einfach der Konstanten eine 2er Potenz zu. Sagen wir in diesem Fall z1 = 1, z2 = 2 (was natürlich den beiden ersten Zweierpotenzen entspricht).
Hier gibt es 4 Möglichkeiten (Anzahl der Zustände ^ 2, da jedes Bit gesetzt sein kann oder nicht). Entweder ist z1 und z2 gesetzt oder nur z1 oder nur z2 oder keins.
Binär ist das 11, 01, 10, 00 (ok, denke dir einfach führende nullen für jeden größeren Datentyp!).
Der Zustand z1 ist dabei die Zahl 1, binär (hier mal als Byte) also 00000001
Der Zustand z2 ist dabei die Zahl 2, binär (hier mal als Byte) also 00000010
Wenn du mit Bits arbeitest, dann kannst du diese sehr leicht mit Bitmasken manipulieren. Und, Oder, Nicht, XOR, NOR, NAND, ... sind alles Verknüpfungen die du mit den Bits und einer Maske ausführen kannst. Wichtig sind in den meisten Fällen Und und Oder.
Schauen wir uns einfach mal die beiden an:
Und ist immer dann 1, wenn beide Bits 1 sind.
Oder ist immer dann 1, wenn mind. eins der Bits 1 ist.
Warum also hier oder?
00000010 oder
00000001
---------
00000011 // die Stellen sind eins, wo mindestens eine 1 stand!
Hier siehst du auch, warum die Konstanten nur 2er Potenzen sein dürften. Jede binäre Zahl setzt sich nur aus einer Summe von zweier Potenzen zusammen, alle anderen Werte würden mehr als ein Bit zur Kodierung benötigen (du könntest also weniger Zustände kodieren oder hättest Veränderungen von mehr als einem Zustand).
Ok, was im Ergebnis steht ist nichts anderes als die 3, also warum nicht addieren?
Den Unterschied merkst du immer dann, wenn du ein Bit setzen möchtest ohne den alten Zustand zu verlieren. Sagen wir du weißt gar nicht wie der alte Zustand aussieht, du möchtest aber unbedingt z2 setzen.
Bei der Addition würde folgendes passieren:
01000010 + // alter Zustand
01000010 // setzen von z2
---------
00000100 // 2 + 2 = 4, 4 <> z2 gesetzt!
Mit dem Oder:
01000010 oder // alter Zustand
00000010 // setzen von z2
---------
01000010 // da 1 wo mindestens eine 1 Stand, erwarteter Zustand!
Wie du hier siehst, wird der alte Zustand beim Oder bei behalten und es wird das neue Bit auf jeden Fall gesetzt. War es schon gesetzt, so ändert sich an diesem Bit nichts.
Wenn du nun im Programm wissen möchtest ob ein Zustand in so einer Variablen gesetzt ist, verwendest du die Eigenschaften einer speziellen Bitmaske und das logische Und. Und ist immer wahr, wenn beide Bits (die Verglichen werden) 1 sind. Wenn du also wissen willst ob ein Bit gesetzt ist, darf deine Maske nur an dieser Stelle 1 sein. Eine Und-Verknüpfung liefert dir dann einen Wert > 0 wenn das Bit gesetzt war. Prüfen wir am letzten Ergebnis ob z1 und z2 gesetzt sind:
Prüfen ob z1 gesetzt:
010000010 und // letztes Ergebnis
000000001 // Bitmaske für z1
----------
000000000 // nicht > 0, damit kein z1 gesetzt
Prüfen ob z2 gesetzt:
010000010 und // letztes Ergebnis
000000010 // Bitmaske für z2
----------
000000010 // > 0, damit z2 gesetzt
So, deswegen verwendet man dort einfach die Oder-Verknüpfung. Sie ist hier als logisches Oder (auf Bitebene) zu verstehen. Die könntest du häufiger finden (gerade wenn es näher in Richtung
API geht). Es ist eine durchaus übliche Art und Weise einfache Zustände zu kodieren, gerade wenn du in die Mikroprozessor Programmierung gehst (wo man nicht immer Massen an Speicher hat und auch gar nicht möchte).
Zitat von
DGL-luke:
Macht man das nicht seit neuestem so:
TFileStream.Create(FileName, fmOpenRead, fmShareExclusive); //man beachte das Komma
Echt? Ab welcher Version ist dass denn erlaubt? Kenne ich noch gar nicht. Also wenn das klappt, klar, noch schöner.