Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

 << zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch für Linux, Unix und Windows
– 2., aktualisierte und erweiterte Auflage 2006
Buch: C von A bis Z

C von A bis Z
1.116 S., mit CD, Referenzkarte, 39,90 Euro
Galileo Computing
ISBN 3-89842-643-2
gp Kapitel 17 Strukturen
  gp 17.1 Struktur deklarieren
  gp 17.2 Initialisierung und Zugriff auf Strukturen
  gp 17.3 Strukturen als Wertübergabe an eine Funktion
  gp 17.4 Strukturen als Rückgabewert einer Funktion
  gp 17.5 Strukturen vergleichen
  gp 17.6 Arrays von Strukturen
  gp 17.7 Strukturen in Strukturen (Nested Structures)
  gp 17.8 Kurze Zusammenfassung zu den Strukturen
  gp 17.9 Union
  gp 17.10 Aufzählungstyp enum
  gp 17.11 Typendefinition mit typedef
  gp 17.12 Attribute von Strukturen verändern (nicht ANSI C)
  gp 17.13 Bitfelder
  gp 17.14 Das offsetof-Makro


Galileo Computing - Zum Seitenanfang

17.9 Union  toptop

Eine weitere Möglichkeit, Daten zu strukturieren, sind Unions (auch Varianten genannt). Abgesehen von einem anderen Schlüsselwort, bestehen zwischen Unions und Strukturen keine syntaktischen Unterschiede. Der Unterschied liegt in der Art und Weise, wie mit dem Speicherplatz der Daten umgegangen wird. Hierzu ein Beispiel der Speicherplatzbelegung einer Struktur:

struct test1 {
   char a;
   int b;
   double c;
};

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 17.8   Speicherbelegung bei einer Struktur

Diese Struktur benötigt 16 Byte an Speicher. Das gleiche Beispiel jetzt mit dem Schlüsselwort union:

union test2 {
   char a;
   int b;
   double c;
};

Intern sieht dies mit union folgendermaßen aus:

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 17.9   Speicherbelegung einer Struktur mit dem Schlüsselwort union

Hierzu ein Listing, welches den Unterschied demonstrieren soll:

/* union1.c */
#include <stdio.h>
#include <stdlib.h>
struct test1 {
   char a;
   int b;
   double c;
};
union test2 {
   char a;
   int b;
   double c;
};
int main(void) {
   printf("struct benoetigt %d Bytes\n", sizeof(struct test1));
   printf("Union  benoetigt %d Bytes\n", sizeof(union test2));
   return EXIT_SUCCESS;
}

Die Struktur mit dem Schlüsselwort union besitzt jetzt nur noch acht Bytes?! Dies verursacht das Schlüsselwort union und das größte Element in der Struktur, double. Dieser ersparte Speicherplatz wird allerdings mit dem Nachteil erkauft, dass immer nur ein Element in dieser Struktur verwendet werden kann. Beispielsweise wird dem Strukturelement int b der Wert 100 übergeben:

text.b = 100;

Somit beträgt die Speichergröße der Struktur trotzdem acht Bytes für einen Integer, da der größte Datentyp in der union nämlich double lautet. Übergeben Sie jetzt an double c den Wert 10.55:

text.c = 10.55;

Jetzt können Sie auf den Wert von int b nicht mehr zugreifen, da dieser von double c überlappt wurde. Zwar kann es immer noch sein, dass int b weiterhin den Wert 100 ausgibt, aber dies wäre Zufall, denn der Speicherbereich wurde überdeckt. Das Verhalten ist in diesem Fall undefiniert.

Welchen Vorteil hat es, wenn immer auf ein Element einer Struktur zugegriffen werden kann? Der wesentliche Vorteil liegt in der Anwendung von Union zum Einsparen von Speicherplatz bei der Verarbeitung großer Strukturen; beispielsweise bei Strukturen, wo bestimmte Elemente niemals miteinander auftreten. Ein Computerspiel z.B., bei dem sich immer einer gegen einen, Auge um Auge, duelliert. In dem folgenden Codeabschnitt wurde eine Struktur mit vier verschiedenen Gegnercharakteren erstellt:

struct gegner {
   union {
      struct {
         char name[20];
         int power;
         unsigned char leben;
         unsigned int geschwindigkeit;
      } fighter1;
      struct {
         char name[20];
         int power;
         unsigned char leben;
         unsigned int geschwindigkeit;
      } fighter2;
      struct {
         char name[20];
         int power;
         unsigned char leben;
         unsigned int geschwindigkeit;
      } fighter3;
      struct {
         char name[20];
         int power;
         unsigned char leben;
         unsigned int geschwindigkeit;
      } fighter4;
   };
} dat;

Damit wird immer nur auf eine Struktur zugegriffen, was in diesem Beispiel ausreichend ist, denn es sollten immer nur die Daten eines Gegners im Speicher sein, eben die, die im Augenblick nötig sind. So könnten Sie z.B. den fighter4 mit Werten initialisieren:

strcpy(dat.fighter4.name, "Superman");
dat.fighter4.power = 5;
dat.fighter4.leben = 1;
dat.fighter4.geschwindigkeit = NORMAL;

Der Zugriff auf die einzelnen Elemente erfolgt wie bei den normalen Strukturen.

Zurück zum Programm der Adressverwaltung, denn dieses eignet sich auch prima für eine Union:

struct adres {
   union {
      struct {
         char vname[20];
         char nname[20];
         long PLZ;
         char ort[20];
         int geburtsjahr;
      } privat;
      struct {
         char vname[20];
         char nname[20];
         long PLZ;
         char ort[20];
         char sternzeichen[20];
         int geburtsjahr;
      } geschaeftlich;
   };
} adressen[100];

Hiermit können 100 Adressen gespeichert werden. Mithilfe dieser Union wird das Private vom Geschäftlichen getrennt.

Natürlich können Sie mit dem Schlüsselwort union auch ein Array von Unions realisieren. Der Zugriff und die Initialisierung erfolgen genauso wie bei den Strukturen bereits beschrieben. Ein Beispiel:

/* union2.c */
#include <stdio.h>
#include <stdlib.h>
union number {
   float x;
   int y;
};
int main(void) {
   union number mixed[2];
   mixed[0].x = 1.123;
   mixed[1].y = 123;
   mixed[2].x = 2.345;
   printf("%.2f\t%d\t%.2f\n",
      mixed[0].x, mixed[1].y, mixed[2].x);
   return EXIT_SUCCESS;
}

Wenn Sie eine Union initialisieren, erlaubt ANSI C nur einen Initialisierer. Und standardmäßig bedeutet dies, dass immer das erste Element der Union initialisiert wird. Es gibt keine Standardlösung, um die anderen Elemente zu initialisieren. Ein Beispiel:

union 2_D  {
   int x;
   int y;
};
// coordinate.x hat den Wert 123
union 2_D coordinate = { 123 };

Achtung   Sollten Sie vorhaben, Ihre Programme auf andere Systemen zu portieren, so müssen sie sich hundertprozentig mit dem Alignment diverser Systeme auskennen, sofern Sie Unions einsetzen wollen. Ansonsten dürften Sie Probleme mit der Portierung bekommen.


 << zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z
C von A bis Z
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Shell-Programmierung






 Shell-Programmierung


Zum Katalog: Linux-UNIX-Programmierung






 Linux-UNIX-Programmierung


Zum Katalog: C/C++






 C/C++


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Reguläre Ausdrücke






 Reguläre Ausdrücke


Zum Katalog: Linux






 Linux


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo





Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de