Bemerkung:
In der Nachfolgesprache Oberon hat Pascal-Entwickler N. Wirth die varianten
Records "abgeschafft".
Variante Records erlauben den Einbau von Komponenten, deren Typ abhängig
ist vom Wert einer anderen Komponente, die als Selektor bezeichnet
wird.
Der Selektor muß einen ordinalen Datentyp besitzen !
Ein Datentyp für variante Records wird wie folgt vereinbart:
TYPE name = RECORD
CASE selektor: typ OF
konstante_1: ( komponente_11; ...; komponente_1n1 );
...
konstante_m: ( komponente_m1; ...; komponente_mnm )
END;
komponente steht wie bereits oben notiert für eine der beiden
folgenden Varianten:
komponenten_name : typ; komponenten_name_1, ..., komponenten_name_k : typ;Der Selektor ist, abgesehen von seiner Schaltfunktion, eine Komponente des Records und wird bei Bezugnahmen wie alle anderen Komponenten angesprochen.
Die Komponentengruppe ( komponente_1; ...; komponente_n ) darf
leer sein: ( ).
Die Anzahl der Komponenten pro Gruppe darf zwischen den verschiedenen
Varianten variieren.
Für typ darf in einigen Pascal-Versionen kein anonymer Datentyp, sondern nur ein Typbezeichner angegeben werden.
Beispiel:
TYPE koordinat = RECORD
CASE typ : (karthesisch, polar) OF
karthesisch : ( x, y : REAL );
polar : ( r : REAL; phi : INTEGER );
END;
VAR pkt1, pkt2 : koordinat;
pkt1.typ := karthesisch;
pkt1.x := 0.5;
pkt1.y := 1.2;
pkt2.typ := polar;
pkt2.r := 0.8;
pkt2.phi := 90;
Bemerkung: Die Besonderheit beim varianten Record besteht darin, daß die alternativen Komponentengruppen den gleichen Speicherplatz belegen !
Achtung:
Es muß damit gerechnet werden, daß unabhängig vom
jeweiligen Wert des Selektors auf alle Varianten zugegriffen werden
kann.
Variante Records sind deshalb anfällig gegenüber Fehlern.
Ein varianter Record kann auch wie folgt vereinbart werden:
TYPE typ = ( konstante_1, ..., konstante_m );
name = RECORD
CASE typ OF
konstante_1: ( komponente_11; ...; komponente_1n1 );
...
konstante_m: ( komponente_m1; ...; komponente_mnm )
END;
Auch in diesem Fall steht für alle Varianten ein gemeinsamer
Speicherbereich zur Verfügung. Beispiel (Pascal++):
TYPE datentyp = (int, byt, ch);
rec = RECORD
CASE datentyp OF
int : ( i : INTEGER );
byt : ( b : ARRAY[1..4] OF BYTE );
ch : ( c : ARRAY[1..4] OF CHAR );
END;
INTEGER beansprucht in Pascal++ 4 Byte, BYTE und
CHAR jeweils 1 Byte. Zur Ausgabe eines Wertes vom obigen Typ rec wird die folgende Prozedur verwendet:
PROCEDURE write_rec(r: rec);
VAR k : INTEGER;
BEGIN
WITH r DO BEGIN
Write(i:12);
FOR k:=1 TO 4 DO Write(b[k]:5); Write(' ');
FOR k:=1 TO 4 DO Write(c[k]); Writeln;
END;
END;
Ein Test mit Pascal++ ergibt folgende Ergebnisse:
Wertzuweisungen Ergebnisse
r.i r.c
1 2 3 4
---------------------------------------------------------------------
Sparc Workstation unter Solaris
42 42 0 0 0 42 *
32767 32767 0 0 127 -1 ˜
32768 32768 0 0 -128 0
* 704675840 42 0 -128 0 *
a b c d 1633837924 97 98 99 100 abcd
++ 1633837925 97 98 99 101 abce
---------------------------------------------------------------------
PC unter DOS
42 42 42 0 0 0 *
32767 32767 -1 127 0 0
32768 32768 0 -128 0 0 Ç
* 32810 42 -128 0 0 *Ç
a b c d 1684234849 97 98 99 100 abcd
++ 1684234850 98 98 99 100 bbcd
---------------------------------------------------------------------
++ steht für die Erhöhung des Wertes um 1. Ein Vergleich der auf verschiedenen Rechnerplattformen erzielten Ergebnisse zeigen ein wichtiges Problem:
Bedingt durch die unterschiedliche Byte-Anordnung auf den verschiedenen Rechnern ergeben sich zum Teil unterschiedliche Ergebnisse !Das obige Beispiel deutet aber auch ein interessantes Einsatzfeld für variante Records an:
Es zeigt aber auch die Gefahren: Wird der Wert einer Komponente
verändert, die Teil eines varianten Records ist, so wird damit
zugleich auch der Wert anderer Komponenten verändert.
Geschieht dies versehentlich, so sind - besonders in großen
Programmen - derartige Fehler oft nur schwer zu finden.
Weitere Beispiele zu varianten Records: Byte-Anordnung.
Extended Pascal
Der Varianten-Teil des Records kann einen Zweig enthalten, der dann verwendet wird, wenn der Selektor einen Wert hat, der durch die explizit aufgeführten Varianten nicht abgedeckt wird:
TYPE name = RECORD
CASE selektor: typ OF
konstante_1: ( komponente_11; ...; komponente_1n1 );
...
konstante_m: ( komponente_m1; ...; komponente_mnm );
OTHERWISE ( komponente_k1; ...; komponente_kl );
END;
Ein Record kann sowohl einen varianten als auch einen "normalen" Anteil besitzen:
TYPE name = RECORD
komponente;
...
komponente;
CASE selektor: typ OF
konstante: ( komponente; ...; komponente );
...
konstante: ( komponente; ...; komponente )
END;
Beispiel:
TYPE typ = (ganz, reell, zeichen);
fakten = RECORD
name: PACKED ARRAY[1..20] OF CHAR;
CASE code: typ OF
ganz: (n: INTEGER);
reell: (r: REAL);
zeichen: (c: CHAR);
END;
Variante Records werden - aus gutem Grund - nicht sehr oft verwendet.
Ihr Einsatz sollte genau überdacht werden, da sie nur bedingt zu besser
verständlichen Programmen führen.