Ubungspaket 27 ¨
Definition eigener Datentypen
Ubungsziele: ¨
1. Umgang mit der typedef-Anweisung Skript:
Kapitel: 54 Semester:
Wintersemester 2021/22 Betreuer:
Thomas, Tim und Ralf Synopsis:
F¨ ur viele Programmieranf¨ anger und leicht Fortgeschrittene erscheint
die typedef-Anweisung einigermaßen ¨ uberfl¨ ussig. Als Lernender mag
man sogar annehmen, dass es diese Anweisung nur zu ihrer Verwirrung
gibt. Aber auch diese Anweisung hat, wie so viele andere Sprachelemen-
te, in der Programmiersprache C ihren Sinn und ihre Berechtigung. In
diesem ¨ Ubungspaket werden wir die Anwendung dieser Anweisung von
verschiedenen Seiten beleuchten und hoffen, dass bei euch dar¨ uber auch
weitere Einsichten von ganz alleine kommen.
Teil I: Stoffwiederholung
Aufgabe 1: Motivation und Datentypen
Erkl¨are kurz in eigenen Worten, was ein Datentyp ist.
Ein Datentyp hat einen Namen und legt fest, wie viele Bits er hat und wie diese Bits zu interpretieren sind. Ein typisches Beispiel ist der Datentyp char: Er umfasst meist acht Bits und erlaubt die Speicherung normaler ASCII Zeichen. Ein etwas komplizierteres Beispiel iststruct cplx { double re, im; }, der aus zweidouble-Werten besteht und gemeinhin als
”komplexe Zahl“ verstanden wird.
Bei welchen Datenstrukturen f¨angt die Sache f¨ur dich an, un¨ubersichtlich zu werden?
Zeiger auf Zeiger, Zeiger auf Zeiger auf Zeiger, Zeiger auf Strukturen
Ein weit verbreiteter Problembereich betrifft die Definition von Zeigern. Einen Zeiger auf einen int-Wert k¨onnten wir beispielsweise auf eine der beiden folgenden Arten definieren:
int *p und int* p. Der immer wiederkehrende Streit betrifft die Frage, wo denn nun der Stern am besten stehen sollte. Eine Antwort lautet: dem Compiler ist es so was von egal. . . Er mag genauso gerne die Variante int*p.
Die Anh¨anger der Variante int* p argumentieren, dass der Stern zum Typ geh¨ort und deshalb beim Wort
”int“ stehen sollte. Nehmen wir an, wir h¨atten folgende Definition:
int* p, q. Die Variablen p und q haben die folgenden Typen: p: int * q: int Dies ist oft nicht das, was man eigentlich haben m¨ochte.
Nehmen wir an, wir h¨atten folgendes Programm:
1 # d e f i n e I N T _ P T R int * 2
3 I N T _ P T R p , q ;
von welchem Typ sind jetzt die beiden Variablen? p: int * q: int
Schlussfolgerung: Auch diese #define-Variante bringt uns kein St¨uck weiter.
Was wir br¨auchten, bildlich gesprochen, ist ein Mechanismus, der uns das Sternchen vor jede Variable schreibt. Und genau das macht typedef.
Wie lautet die Syntax der typedef-Anweisung? typedef <alter Typ> <neuer Typ>
Bei der typedef-Anweisung sind zwei Dinge wichtig:
1. Alle neuen Typen werden immer auf die Basistypen zur¨uckgef¨uhrt.
2. Die neuen, selbstdefinierten Typen kann man so verwenden, als g¨abe es sie schon immer.
Teil II: Quiz
Aufgabe 1: typedef I: einfache Beispiele
Nehmen wir an, wir h¨atten ein Programm, in dem die folgenden Typ- und Variablendefi- nitionen gegeben sind:
1 t y p e d e f int m y I n t ; 2 m y I n t m i _ i n d e x ; 3
4 t y p e d e f c h a r Zeichen , c h a r L a b e l ; 5 Z e i c h e n l a b _ 1 ;
6 c h a r L a b e l l a b _ 2 ; 7
8 t y p e d e f int p e r s o n a l I D , * P I D _ P T R ; 9 p e r s o n a l I D c l a s s _ m a t e , * m a t e _ p ; 10 P I D _ P T R c m _ i n d e x , * c m _ p p ; 11
12 t y p e d e f p e r s o n a l I D * LOOPI , ** L O O P I I ;
Trage nun in folgende Tabelle jeweils den neu definierten Datentyp bzw. den Datentyp der angegebenen Variablen ein. Zur Illustration sind die ersten beiden Beispiele bereits vorgegeben.
Zeile Name resultierender C-Typ Beschreibung
1 myInt int einfacher Datentyp int
2 mi index int einfacher Datentyp int 4 Zeichen char einfacher Datentyp char
charLabel char einfacher Datentyp char 5 lab 1 char einfacher Datentyp char 6 lab 2 char einfacher Datentyp char 8 personalID int einfacher Datentyp int
PID PTR int * Zeiger auf int
9 class mate int einfacher Datentyp int
mate p int * Zeiger auf int
10 cm index int * Zeiger auf int
cm pp int ** Zeiger auf Zeiger auf int
12 LOOPI int * Zeiger auf personalID und damit Zeiger auf int
LOOPII int ** Zeiger auf Zeiger auf personalID und damit Zeiger auf Zeiger auf int
Aufgabe 2: typedef II: Arrays und Zeiger
Nun schauen wir ein wenig auf Arrays und Zeiger:
1 t y p e d e f c h a r * S T R I N G ; 2 t y p e d e f S T R I N G * S T R _ P T R ; 3
4 t y p e d e f c h a r L A B E L [ 5 ];
5 L A B E L label , * l _ p t r ; 6
7 t y p e d e f int VEC [ 3 ] , * XP ; 8 VEC vec , * vp1 ;
9 XP ip ; 10
11 t y p e d e f VEC * V _ P T R ; 12 V _ P T R vp2 , * vp3 ;
Trage in folgende Tabelle jeweils den neu definierten Datentyp bzw. den Datentyp der ange- gebenen Variablen ein. Zur Illustration sind die ersten beiden Beispiele bereits vorgegeben.
Die ¨ubliche Annahme ist, dass Zeiger und int-Werte jeweils vier Bytes ben¨otigen.
Zeile Name resultierender C-Typ Beschreibung 1 STRING char * Zeiger auf char
STR PTR char ** Zeiger auf STRING ergibt Zeiger auf Zeiger auf char
4 LABEL char [ 5 ] char-Array mit f¨unf Elementen.
Beispiel: LABEL l und char l[ 5 ] sind identisch 5 label char [5] Array mit f¨unf Elementen vom Typ char
Equivalent:char label[ 5 ]
l ptr char (*)[5] Zeiger auf ein Array mit f¨unf Elementen:
sizeof(* l ptr) == 5 7 VEC int [3] Array mit dreiint-Werten
XP int * Zeiger aufeinen int-Wert 8 vec int vec[3] Array mit dreiint-Werten
vp1 int (*)[3] Zeiger auf VEC ergibt Zeiger auf int [3]
sizeof(*vp1) == 12 und sizeof(**vp1) == 4
9 ip int* Zeiger auf int; nahezu langweilig
11 V PTR int (*)[3] Zeiger auf einint-Array mit drei Elementen 12 vp2 int (*)[3] absolut identisch mitvp1
vp3 int (**)[3] Zeiger auf V PTR ist Zeiger auf Zeiger auf VEC ist Zeiger auf Zeiger auf int [3]
sizeof(*vp3) == 4, sizeof(**vp3) == 12 und sizeof(***vp3) == 4
Aufgabe 3: typedef III: Zeiger Strukturen
Zum Schluss noch ein paar Beispiele zu Strukturen:
1 t y p e d e f s t r u c t bsp { c h a r c1 ; c h a r c2 ; } S T R U C T 1 ; 2
3 t y p e d e f s t r u c t { c h a r c1 , c2 ; } STRUCT2 , * S2P ; 4
5 t y p e d e f s t r u c t xyz { int * ip ; int i ; } XYZ ; 6
7 t y p e d e f s t r u c t _ e l e m e n t {
8 s t r u c t _ e l e m e n t * n e x t ;
9 int v a l u e ;
10 } ELEMENT , * E _ P T R ;
Trage in folgende Tabelle jeweils den neu definierten Datentyp bzw. den Datentyp der angegebenen Variablen ein.
Zeile Name
”ausgeschriebener“ Typ
1 STRUCT1 struct bestehend aus zwei Zeichen.
Diese Struktur ist auch unter dem Namenstruct bsp bekannt.
3 STRUCT2 identisch mitSTRUCT1, aber keine Alternative verf¨ugbar, da nachstruct kein Name steht.
S2P Zeiger auf eine Struktur, die aus zwei Zeichen besteht
5 XYZ Dies ist eine Struktur mit einem Zeiger auf einintsowie einemint-Wert.
10 ELEMENT ELEMENTist eine Struktur, die einenint-Wert sowie einenZeiger auf sich selbst enth¨alt.
E PTR Zeiger auf die StrukturELEMENT
Teil III: Fehlersuche
Aufgabe 1: Variablendefinitionen mittels typedef
Offensichtlich ben¨otigt auch Dr. Type-De-Fooletwas Unterst¨utzung.
1 # d e f i n e S P E C I A L _ C H A R c h a r * 2
3 S P E C I A L _ C H A R c h a r _ p t r , o n e _ c h a r ; 4 S P E C I A L _ C H A R c h a r _ p t r 1 , c h a r _ p t r 2 ; 5
6 t y p d e f int m y I n t a l s o M y I n t ; 7
8 m y I n t * o n e _ i n t ;
9 a l s o M y I n t i_ptr1 , i _ p t r 2
Zeile Fehler Erl¨auterung Korrektur
3 Unglaublich, aber hier ist alles richtig.
. . . .
4 * fehlt Die zweite Variable (char ptr2) ist nur ein Zeichen und kein Zeiger, da es sich bei SPECIAL CHAR um ein
#define und nicht ein typedef handelt.
* char ptr2
. . . .
6 Tippfehler Die Anweisung typedefist falsch geschrieben typedef
. . . .
6 Komma fehlt
Das Komma zwischen den beiden Typen myInt und alsoMyInt fehlt
myInt,
. . . .
8 * zu viel Da hier eine einfache int-Variable gew¨unscht wird, ist das Sternchen zu viel.
myInt one int
. . . .
9 * fehlen DeralsoMyIntein normalerint-Typ ist, m¨ussen f¨ur die zwei Zeiger Sternchen verwendet werden.
*i ptr1,
*i ptr2
Programm mit Korrekturen:
1 # d e f i n e S P E C I A L _ C H A R c h a r * 2
3 S P E C I A L _ C H A R c h a r _ p t r , o n e _ c h a r ; 4 S P E C I A L _ C H A R c h a r _ p t r 1 , * c h a r _ p t r 2 ; 5
6 t y p e d e f int myInt , a l s o M y I n t ; 7
8 m y I n t o n e _ i n t ;
9 a l s o M y I n t * i_ptr1 , * i _ p t r 2
Teil IV: Anwendungen
Aufgabe 1: Eigenst¨ andige Definition neuer Datentypen
In dieser Aufgabe sollt ihr gem¨aß Spezifikation eigene Datentypen mittelstypedefbilden.
1. Definiere einen eigenen Typ myDP, der ein Zeiger auf ein double ist.
typedef double *myDP;
2. Definiere einen eigenen Typ myCP sowie myCPP der ein Zeiger auf ein char bzw. ein Zeiger auf ein Zeiger auf einchar ist.
typedef char *myCP, **myCPP;
3. Definiere einen Typ myTag, der genau zehn Zeichen aufnehmen kann.
typedef char myTag[ 10 ];
4. Definiere einen Typ myTagPtr, der ein Zeiger auf den TypmyTag ist.
typedef myTag *myTagPtr;
5. Definiere einen Typ C ARRAY, der vier Zeiger auf ein Zeichen besitzt. F¨uhre die De- finition einmal mittels des Typs myCP aus der zweiten Aufgabe und einmal direkt durch.
typedef myCP C ARRAY[ 4 ];
typedef char *(C ARRAY[ 4 ]);
6. Definiere eine Struktur Auto, die die Zahl der R¨ader sowie die Motorleistung aufneh- men kann.
typedef struct { int raeder; int PS; } Auto;
7. Definiere einen Zeigertyp AutoPtr, der auf ein Auto zeigt.
typedef Auto *AutoPtr;