|
|
|
|
|
|
|
|
| .. Varianten - union | ||
|
|
||
|
|
|
|
union zahlen { int i;
double x;
char c;
} z;
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Unions oder Varianten sind eine Art Variable mit einer Untervariablen, bei der die Untervariable allerdings unterschiedliche Typen besitzen kann. Anders als bei der Struktur (struct) teilt sich die eine Untervariable den verfügbaren Speicherraum der union mit den anderen möglichen Variablen der alternativen Variablentypen.
Dementsprechend bestimmte der Variablentyp mit dem grössten Speicherbedarf den von der union belegten Speicherplatz. Bei der unten angegebenen Union ist das die Fliesskommavariable x mit 8Byte. denn für den Integer i werden 2 Bytes, für die Fliesskommazahl x, 8 Bytes und für den Character c, 1 Byte benötigt.
Beispiel 1: |
|
union {
int i;
double x;
char c;
} y, z;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
union zahl {
int i;
double x;
char c;
};
|
|
|
|
|
Im oberen Beispiel wird eine Union mit dem Namen Zahl deklariert. In der Folge kann der Name dieser Union wie ein Typbezeichner verwendet werden, so dass man zu beliebiger Zeit, Variable von der Art dieser Union erzeugen kann. Beispielsweise ..
union zahl y; oder an andere Stelle .. union zahl z;
Wie bereits angemerkt kann jede dieser zwei Variablen y und z, zu einer Zeit, eine der Untervariablen i, x, und c, deren Variablentypen voneinander abweichen, aufnehmen. |
|
|
|
|
|
|
|
|
|
typedef struct {
int i;
double x;
char c;
} zahl;
|
|
|
|
|
Wen es stört, dass man vor den Namen des Union-Variablentyps immer union schreiben muss, der kann mit der Präprozessordirektive typedef arbeiten. Die funktioniert ein Stück weit wie #define. Es wird also das gesamte Literal union { ...} hinter dem Ausdruck zahl verborgen. Nun kann man so tun, als sei der Unionname zahl ein eigenständiger Variablentyp, denn man darf schreiben ..
zahl y; oder an andere Stelle .. zahl z;
.. was indirekt dem Beispiel 1 ähnlich ist. Wie bereits angemerkt kann jede dieser zwei Variablen y und z, zu einer Zeit, eine der Untervariablen i, x, und c, deren Variablentypen voneinander abweichen, aufnehmen. |
|
|
|
|
|
|
|
Deklaration und Initialisation Der nachfolgende Ausdruck wird zwar vom Compiler nicht mit einer Fehlermeldung begleitet und würde auch für die Integervariable int i, sowie die Charactervariable char c zur Übernahme eines richtigen Wertes führen, bei dem Versuch den Speicher der Union mit einer Fliesskommazahl double x zu füllen schlägt er aber fehl. Kurz und gut, die sichere Initialisation der Union auf diesem Weg ist nicht möglich.
UnBeispiel: zahl z = {1234}; // funktioniert zwar zahl z = {1234.57}; // funktioniert nicht |
|
|
|
|
|
|
|
Bei Unions ist es (anders als bei Strukturen ) nicht möglich, jeder Untervariablen gleichzeitig einen eigenen Wert einzuschreiben. Das nachfolgende Programm zeigt diese Eigenschaften aus der Warte des Programmierers.
Ein Beispielprogramm
|
|
|
|
|
|
// union.cpp
// ------------ Version 17.06.2007
// Borland IDE C++ 3.1 oder 5.02
// Model: SMALL
// Char: unsigned
// bearbeitet: www.GoBlack.de, D.Schwarzer
// Hardware: jeder DOS-PC
#include <stdio> // für printf()
#include <conio> // für getch()
// typedef union {int i; double x; char c;} zahl; // Alternative
union zahl {int i; double x; char c;};
// Dieser Programmteil liest die 11 Bytes der übergebenen Variablen
// z vom Typ (union) zahl und gibt sie samt Anfangsadresse
// aufeinanderfolgend zum Bildschirm aus.
void scan_union(zahl z)
{
int n=0;
char* m;
m = (char*)&z;
printf ("\n Adr von z: %X - Inhalt: ", &z);
for (n=sizeof(z)-1; n>=0; n--){printf("%02X", *(m+n));}
}
// das Beispielprogramm ermittelt für die Variable z und
// jede ihrer Untervariablen z.i, z.x, z.c die Anzahl der
// belegten Bytes, sowie deren Anfangsadressen im Speicher
// dann wird jeder der drei Untervariablen ein legaler
// Wert zugewiesen und beobachtet zu welchem Resultat das
// bei der Füllung der Struktur und ihrer Untervariablen
// führt.
void main (void)
{
// Deklaration und Definition einer Variablen z vom neuen Typ
// (union)zahl. Sie kann nur einen Wert aufnehmen
union zahl z={0};
// Anzahl der belegten Bytes im Speicher und ..
// Anfangsadresse der Variablen
printf ("\nbelegte Bytes im Speicher / AnfangsAdresse");
printf ("\nz = %2d Adr: %04Xh", sizeof(z), &z);
printf ("\nz.i = %2d Adr: %04Xh", sizeof(z.i), &z.i);
printf ("\nz.x = %2d Adr: %04Xh", sizeof(z.x), &z.x);
printf ("\nz.c = %2d Adr: %04Xh", sizeof(z.c), &z.c);
printf ("\n-----");
// Wert für z.i => noch keine Werte für z.x und z.c
z.i = 0x1234;
scan_union(z);
printf ("\n Wert fuer IntegerVariable z.i");
printf ("\nInhalt hex z.i = %04Xh", z.i);
printf ("\nInhalt float z.x = %g", z.x);
printf ("\nInhalt hex z.c = %02Xh", z.c);
printf ("\n-----");
// Wert für z.x => noch kein Wert für z.c
z.x = 1234.57;
scan_union(z);
printf ("\n Wert fuer FliesskommaVariable z.x");
printf ("\nInhalt hex z.i = %04Xh", z.i);
printf ("\nInhalt float z.x = %g", z.x);
printf ("\nInhalt hex z.c = %02Xh", z.c);
printf ("\n-----");
// Wert für z.c => Struktur ist gefüllt
z.c = 0xC3;
scan_union(z);
printf ("\n Wert fuer CharacterVariable z.c");
printf ("\nInhalt hex z.i = %04Xh", z.i);
printf ("\nInhalt float z.x = %g", z.x);
printf ("\nInhalt hex z.c = %02Xh", z.c);
getch();
}
|
||
|
|
|
|
|
|
|
|
|
|
Der Ausgabebildschirm des obigen Programms. Zu beachten ist, dass die Zuweisung von Adressen der Variablen zur Laufzeit erfolgt, .. sie können also bei jedem Lauf des Programms andere Werte annehmen. |
|
|
|
|
|
|
|
|
|
|
|
.de