![]() |
![]() |
C++ - Varianten |
G.Eichelsdörfer - Staatliche Technikerschule Weilburg |
Das letzte Anwendungsbeispiel zu Bitfelder zeigte, wie einfach einzelne Bits oder Bitgruppen abgefragt (P.RefX) oder mit Werten belegt (P.MotX = -1) werden können. Typischerweise sollen alle Komponenten eines geeignet zusammengestellten Structs zugleich von einem Port eingelesen oder an einem Port ausgegeben werden. Dies ist jedoch mit den bisherigen Mitteln nicht möglich.
Was brauchen wir dafür?
Einmal brauchen wir einen Zugriff auf den gesamten Struct, ein anderes Mal wollen wir auf einzelne Komponenten zugreifen. Es ist also eine (zusammengesetzte) Variable mit "zwei Gesichtern" erforderlich. Der Typ einer solchen Variablen wird in C/C++ union genannt.
Wie wird ein Union erstellt?
Ein Union wird genau so deklariert wie ein Struct. Während jedoch in einem Struct alle Komponenten unabhängig voneinander hintereinander liegen, bezeichnen alle Varianten eines Union dieselben Daten. Was als Bitfeld hineingeschrieben wurde, kann beispielsweise als Integer gelesen werden und umgekehrt.
Beispiel für den Zugriff auf die Bytes einer int-Variablen:
Legen Sie ein Union so an wie einen Struct! Den Namen dürfen Sie nach Bedarf wählen.
union Integer
{};
Legen Sie darin die erste Variante an!
union Integer
{
int Zahl;
};
Erweitern Sie das Union um eine zweite Variante!
union Integer
{
int Zahl;
unsigned char Byte[4];
};
Bei Bedarf können Sie weitere Varianten einbauen. Beachten Sie, dass alle diese Varianten Zugriff auf dieselben Daten gewähren.
Nun können Sie mühelos auf einzelne Bytes einer int-Zahl zugreifen.
Dazu wird wie bei Structs die Punktnotation verwendet.
Integer I;
I.Zahl = 1000000;
for(int i=3; i>=0; --i)
cout << (int)I.Byte[i] << ", ";
Ausgaben: 0, 15, 66, 64, (Die Wertigkeiten der Bytes sind:
2563,2562,2561, 2560)
Sie mögen das überprüfen: 15*2562 + 66*256 + 64 = ...
Das Datenfeld "Byte" besteht aus 4 Bytes, die int-Variante Zahl auch. Beide Varianten verwenden dieselben Bytes. Die Varianten müssen jedoch nicht gleich groß sein. Für eine Union-Variable wird genau so viel Speicherplatz reserviert wie die größte Variante benötigt.
Um die Positionierungsanlage mit Hilfe der Bitfelder der letzten Seite komfortabel steuern zu können muss der dort erstellte Struct "Pos" als Variante in ein Union eingesetzt werden. Links sehen Sie noch einmal den zuvor deklarierten Struct "Pos".
struct Pos
|
union PortValue
|
Nun kann per Variante "Byte" auf alle 8 Bits zugegriffen werden,
während der Zugriff auf die einzelnen Bitfelder per Komponente "Bits" erfolgt.
Dies soll mit dem folgenden Beispiel verdeutlicht werden:
PortValue PV;
PV.Byte = einlesen(); // einlesen() liest ein Byte ein.
while(!PV.Bits.RefX || !PV.Bits.RefY) // Zugriff auf zwei Bits des eingelesenen Byte
{
if(PV.Bits.RefX) PV.Bits.MotX = 0; else PV.Bits.MotX = -1;
if(PV.Bits.RefY) PV.Bits.MotY = 0; else PV.Bits.MotY = -1;
ausgeben(PV.Byte); // ausgeben() gibt das ganze Byte aus.
PV.Byte = einlesen();
}