Advanced Java Services | typedef |
Mit dem Schlüsselwort typedef kann man ein Alias für einen Datentyp einrichten. Ein Alias kann ein sprechenderer Name sein als z. Bsp. der Name des Datemtyps int und so ein Programm lesbarer machen. In gewissem Sinne funktioniert typedef umgekehrt wie #define, denn bei #define kommt der Aliasname als erstes, bei typedef dagegen am Ende.
#define MAXLEN 50 typedef long bigint;
Hier wird bigint zum Alias für long nach dem Schema
typedef <Datentyp> <AliasName>
und man kann nun bigint an Stelle von long schreiben
bigint grosszahl = 1234567; printf("%ld\n", grosszahl); double dou = 12345; bigint grosszahl2 = (bigint)dou; printf("%ld", grosszahl2);
typedef int* intpoi; int zahl = 17; intpoi ipoi = &zahl; printf("%d\n", *ipoi);
typedef char* string; string st = "Hola"; printf("%s\n", st); st = "Hello"; printf("%s\n", st);
typedef char* const cstring; cstring cs = "pointer is immutable"; //cs = "foo"; // assignment of read-only variable
Ein enum deklarieren und ein Alias mit typedef einrichten.
enum day { monday, tuesday, wednesday, thursday, friday, saturday, sunday }; typedef enum day tag;
oder kürzer
typedef enum day { monday, tuesday, wednesday, thursday, friday, saturday, sunday } tag;
Bei dieser Variante kann man den Bezeichner day auch weglassen. Nun kann man das enum mit Hilfe des neuen Typnamens tag ansprechen.
tag heute = monday; // OK enum day morgen = tuesday; // OK, geht auch
Ein struct deklarieren und ein Alias mit typedef einrichten.
struct person { char vorname[30]; char nachname[30]; }; typedef struct person Person;
oder kürzer
typedef struct person { char vorname[30]; char nachname[30]; } Person;
Bei der zweiten Variante kann man wie bei enum den Bezeichner person auch weglassen. Verwendung:
Person me, myself, i; struct person you; Person *perspoi; Person persarr[5];
Besonders beliebt ist typedef bei Strukturen, die verkettete Listen aufbauen.
typedef struct x { char vorname[30]; char nachname[30]; struct x *next; } Person;
Mit dieser Struktur kann man ein einfach verkettete Liste aufbauen. Der Platzhalter x wird nur gebraucht, um in der Struktur einen Pointer gleichen Typs zu deklarieren.
Skizze einer Verwendung
Listelem begin; strcpy(begin.firstname, heinrich); strcpy(begin.secondname, heine); printf("%s %s\n", begin.firstname, begin.secondname); Listelem follower; strcpy(follower.firstname, gustave); strcpy(follower.secondname, flaubert); follower.next = NULL; begin.next = &follower; Listelem *start = &begin; while( start !=NULL) { printf("%s %s\n", start->firstname, start->secondname); start = start->next; }
Die bisherigen Beispiele könnte man auch mit #define erledigen. Trotzdem ist typedef vorzuziehen. defines werden vom Preprozessor bearbeitet und funktionieren wie Textersatz etwa in Word. Aliasnamen die mit typedef eingeführt wurden, werden dagegen vom Compiler verarbeitet.
Ein Grund für die Verwendung von typedef ist das Vestecken von Typen die von verschiedenen Compilern verschieden definiert werden (müssen), weil sie etwa maschinenabhängig sind. Auf diese Weise kann die Portabilität von Programmen verbessert werden. Die bekanntesten Beispiele hierzu sind die Typen size_t und time_t mit denen mehrere klassische Bibliotheksfunktionen arbeiten.
size_t wird z.Bsp in folgenden Funktionen verwendet (stdio.h)
size_t fread(void*, size_t, size_t, FILE*); size_t fwrite(const void*, size_t, size_t, FILE*);
und in diesen (stdlib.h)
void* calloc(size_t, size_t) void* malloc(size_t)
MINGW z. Bsp. löst den Typ in stddef.h wie folgt auf
typedef __SIZE_TYPE__ size_t;
und
#define __SIZE_TYPE__ long unsigned int
Andere C-Compiler lösen ihn evtl. anders auf.
time_t wird in der folgende Funktion verwendet (time.h)
time_t time(time_t*);
Je nach dem zugrunde liegenden Prozessor löst MINGW den Typ in time.h wie folgt auf
typedef __time64_t time_t;
oder
typedef __time32_t time_t;
Hinter den Typen die mit __t beginnen steht wiederum folgendes:
typedef __int32 __time32_t;
bzw.
typedef __int64 __time64_t;
In _mingw.h werden diese Typen dann aufgelöst zu
#define __int32 long
bzw.
#define __int64 long long
Ein weiterer Grund für die Verwendung von typdef ist seine Mächtigkeit, die vor allem im Zusammenhang mit Funktionspointern sichtbar wird. Hier kann man nicht mehr mit #define arbeiten. Beispiele hierzu folgen nach der Vorstellung von Funktionspointern.