Verbund (Datentyp)
Ein Verbund (englisch object composition) ist ein Datentyp, der aus einem oder mehreren Datentypen zusammengesetzt wurde. Die Komponenten eines Verbunds können wiederum Verbünde sein, wodurch auch komplexe Datenstrukturen definiert werden können.
Die Komponenten/Elemente eines Verbunds werden normalerweise nacheinander im
Speicher angeordnet (beispielsweise als struct
in der Programmiersprache
C bzw. als record
in Pascal).
Eine Ausnahme stellen Unions
dar. Auch in anderen Programmiersprachen
(siehe unten) wird dieser Datentyp zum Teil unterschiedlich bezeichnet.
Verwendung in verschiedenen Programmiersprachen
Strukturen in den Programmiersprachen C++ und C
In den Programmiersprachen C
und C++ werden
Verbünde (engl. auch composite types) als Struktur bezeichnet und
mit dem Schlüsselwort struct
(kurz für engl. structure ‚Struktur‘) deklariert. Die einzelnen
Komponenten einer Struktur, die sog. members
‚Mitglieder‘ dürfen dabei beliebige einfache Datentypen, Felder konstanter Größe
oder ein Zeiger
auf dieselbe Strukturen sein.
Im Gegensatz zur union überlappen sich die Speicherbereiche der einzelnen Strukturmitglieder nicht.
Beispiel in C
#include <stdio.h>
struct Person
{
int PersonalNummer;
int Alter;
char Name[20];
} * pPerson;
void main ()
{
// Aufsuchen des Personaldatensatzes mithilfe des Schlüssels PersonalNummer:
pPerson = ...; // Setzen des Zeigers pPerson auf eine der Strukturen
printf ("PersonalNummer: %i, Alter: %i\n",
pPerson->PersonalNummer,
pPerson->Alter);
}
Hat man einen Zeiger
auf die Struktur, dann wird, wie gezeigt, auf einzelne Members am einfachsten
mithilfe des Pfeils ->
zugegriffen, bspw. pPerson->Alter
.
Der Pfeil (engl. arrow) ist eine Kurzschreibweise für (*pPerson).Alter
mit dem Stern *
als Dereferenzierungsoperator (engl. dereference
operator) und dem Punkt .
als Selektor (engl. object
selector).
Größe im Speicher
Eine Struktur kann größer sein, als die Summe der einzelnen Datentypgrößen, da der Compiler die einzelnen Attribute im Speicher an bestimmten Adressen ausrichten kann. Die Anordnung der Struktur im Speicher ist nach der Übersetzung festgelegt und kann nicht mehr verändert werden.
Unterscheidung zwischen C++- und C-Struktur
In C können Strukturen lediglich Variablen, Zeiger, Arrays und andere Strukturen enthalten, während Strukturen in C++ die zusätzliche Fähigkeit besitzen, Unterprogramme – sogenannte Methoden – zu beinhalten, zu denen auch Konstruktoren und Destruktoren gehören. Dies lässt sich in C nur teilweise über Funktionszeiger realisieren, die auch Teil von Strukturen sein können.
Unterscheidung zwischen C++-Struktur und C++-Klasse
In C++ dienen die Schlüsselwörter public
und
private
dazu, die Zugriffsrechte auf Attribute und Methoden in
Strukturen und Klassen zu regeln. Der einzige Unterschied hier ist, dass ohne
explizite Angabe die Attribute von Strukturen standardmäßig public
(Zugriff von außen erlaubt), die einer Klasse private
(Zugriff nur
von innerhalb der Klasse oder durch Friend-Funktionen)
sind.
Implementierung in Pascal
Ein Verbund (in Pascal mit record
bezeichnet) vom Datentyp
Person
für die beiden Instanzen Mustermann1
und
Mustermann2
könnte in Component
Pascal zum Beispiel folgendermaßen definiert und verwendet werden, und nur
Instanzen desselben Datentyps sind in dieser Programmiersprache zuweisungskompatibel:
MODULE Personen;
IMPORT Dates;
TYPE
Person = RECORD
Vorname, Name, Wohnort: ARRAY 256 OF CHAR;
Geburtstag: Dates.Date;
END;
VAR Mustermann1, Mustermann2: Person;
BEGIN
Mustermann1.Vorname := "Hans";
Mustermann1.Name := "Mustermann";
Mustermann1.Wohnort := "Musterstadt";
Mustermann1.Geburtstag.day := 1;
Mustermann1.Geburtstag.month := 1;
Mustermann1.Geburtstag.year := 1900;
Mustermann2 := Mustermann1; (* Zwei Variablen vom selben Datentyp sind zuweisungskompatibel *)
END Personen.
Der importierte im Modul
Dates
definierte Datentyp Dates.Date
ist wiederum ein
Verbund mit den ganzzahligen Elementen day
(Tag),
month
(Monat) und year
(Jahr).
Datengruppen in Cobol
In Cobol
wird der Datentyp Verbund ‚Datengruppe‘ (auch Gruppen-Variable
oder group item
) genannt. Eine Datengruppe wird mit ihrem
Bezeichner deklariert und ist der Überbegriff bzw. die Zusammenfassung für die
ihr hierarchisch untergeordneten
Datentypen – die selbst wieder Datengruppen sein können. Sie hat selbst keine
Formatspezifikation (PIC-Klausel). Über die OCCURS
-Klausel kann
auch eine Datengruppe als Tabelle (= Array)
deklariert werden, ggf. auch mehrstufig.
In den die Datengruppe ansprechenden Befehlen wird die Gesamtheit der ihr
untergeordneten Felder als ein (1) Datenfeld
im PIC-X-Characterformat und in der Gesamtlänge aller Einzelfelder behandelt.
Bei einem MOVE
-Befehl etwa findet also keine individuelle
formatspezifische Verarbeitung der Einzelfelder statt, auch keine
Formatkonvertierung.
Über die REDEFINES
-Klausel kann eine Datengruppe eine andere
Datengruppe 'redefinieren', wodurch beide Datengruppen denselben Speicherplatz
benutzen. Angewendet wird dies beispielsweise für die Verarbeitung
unterschiedlicher Eingabedaten, alternativ in der einen oder in der anderen
Datenstruktur. Dies entspricht dem Konstrukt UNION in anderen
Programmiersprachen.
Unions
Bei sog. Unions beginnen alle Komponenten an der gleichen Speicheradresse, d.h., ihre Speicherbereiche überlappen sich ganz oder zumindest teilweise. Eine Union belegt dabei mindestens so viel Speicher, wie ihre größte Komponente.
Unions sind in verschiedenen Programmiersprachen entweder als tagged-Unions oder untagged-Unions implementiert.
Eine tagged-Union ordnet jeder Komponente einen Tag zu. Beim Schreiben einer Komponente wird der Tag dieser Komponente in der Union-Variable gespeichert. Bei Lesezugriffen auf die Komponente einer Union wird der Tag der zu lesenden Komponente mit dem Tag der letzten geschriebenen Komponente verglichen. Unterscheiden sich die Tags, ist ein Typfehler festgestellt. Somit sind tagged-Unions typsicher.
Untagged-Unions verwenden keine Tags und sind deswegen typunsicher.
D.h., es liegt in der Verantwortung des Programmierers, ob der letzte
Schreibzugriff einer Union die gleiche Komponente verändert hat, die auch der
darauf folgende Lesezugriff ausliest. Neben unbeabsichtigten Typfehlern bei der
Verwendung von untagged-Unions existieren aber auch Anwendungsfälle für die Seiteneffekte
von untagged-Unions. Beispielsweise eine Union aus einer IEEE-Gleitkommazahl und einer
struct
, deren Komponenten den Zugriff auf Vorzeichen, Mantisse und
Exponent erlauben.
Beispiel in C
#include <stdio.h>
#include <math.h>
#include <inttypes.h>
union Float64Components
{
double Float64;
struct
{
uint64_t Mantissa52 : 52;
uint64_t Exponent11 : 11;
uint64_t Sign1 : 1;
};
};
void main ()
{
union Float64Components pi;
pi.Float64 = 3.1415926535897932384626433832795;
printf ("%20.16f %13I64X %03I64X %01I64X (%20.16f)\n",
pi.Float64,
pi.Mantissa52, pi.Exponent11, pi.Sign1,
(pi.Sign1 ? -1 : +1) * (1.0 + pi.Mantissa52/4503599627370496.0) * pow (2, pi.Exponent11-1023));
}
Output
3.1415926535897931 921FB54442D18 400 0 ( 3.1415926535897931)
Beispiel in Haskell
Beispiel der Deklaration einer Union in Haskell:
data Tree a = Br (Tree a) (Tree a) |
Leaf a |
Nil
Tree ist ein algebraischer Datentyp. Br, Leaf und Nil sind die Konstruktoren.
© biancahoegel.de
Datum der letzten Änderung: Jena, den: 19.05. 2020