15.11 Typendefinition mit »typedef« 

Mit dem Schlüsselwort typedef kann ein neuer Bezeichner für einen einfachen Datentyp verwendet werden. Die Syntax einer einfachen Typendefinition sieht so aus:
typedef Typendefinition Bezeichner;
Damit lässt sich die Lesbarkeit eines Programms erheblich verbessern. Diese Typendefinition mit typedef soll anhand des Adressprogramms demonstriert werden. Hier sehen Sie das Listung dazu:
/* typedef1.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 30
static int x;
struct adres {
char vname[MAX];
char nname[MAX];
long PLZ;
char ort[MAX];
int geburtsjahr;
} adressen[100];
typedef struct adres ADRESSE;
void Eingabe(int nr, ADRESSE *neu) {
printf("Vorname : ");
fgets(neu[nr].vname, MAX, stdin);
printf("Nachname : ");
fgets(neu[nr].nname, MAX, stdin);
printf("Postleitzahl: ");
do {
scanf("%5ld",&neu[nr].PLZ);
} while(getchar()!= '\n');
printf("Wohnort : ");
fgets(neu[nr].ort, MAX, stdin);
printf("Geburtsjahr : ");
do {
scanf("%4d",&neu[nr].geburtsjahr);
} while(getchar()!= '\n');
}
void Suche(ADRESSE *search, char buchstabe, int nr) {
int i;
for(i = 0; i <= nr; i++) {
if(search[i].nname[0] == buchstabe) {
printf("\n\nGefunden unter Buchstabe :\"%c\"\n\n",
buchstabe);
printf("Vorname.......:%s",search[i].vname);
printf("Nachname......:%s",search[i].nname);
printf("Postleitzahl..:%ld\n",search[i].PLZ);
printf("Ort...........:%s",search[i].ort);
printf("Geburtsjahr...:%d\n",search[i].geburtsjahr);
printf("\n\tWeiter mit <ENTER>\n");
getchar();
}
}
}
void Ausgabe(ADRESSE *all, int nr) {
int i;
for(i = 0; i < nr; i++) {
printf("Vorname.........:%s",all[i].vname);
printf("Nachname........:%s",all[i].nname);
printf("Postleitzahl....:%ld\n",all[i].PLZ);
printf("Ort.............:%s",all[i].ort);
printf("Geburtsjahr.....:%d\n\n",all[i].geburtsjahr);
if( (!(i%2)) && i!=0) {
//fflush(stdin);
printf("\n\tWeiter mit <Enter>\n\n");
getchar();
}
}
}
void Sort(ADRESSE *sort,int nr) {
ADRESSE *temp;
int i,j;
temp = malloc(sizeof(ADRESSE *));
if(NULL == temp) {
printf("Konnte keinen Speicher reservieren ...\n");
return;
}
for(i = 0; i < nr; i++) {
for(j=i+1;j<nr;j++) {
if(strcmp(sort[i].nname, sort[j].nname)>0) {
*temp=sort[j];
sort[j]=sort[i];
sort[i]=*temp;
}
}
}
printf("... sortiert!!\n");
}
int main(void) {
int auswahl;
char c;
do {
printf("-1- Neue Adresse eingeben\n");
printf("-2- Bestimmte Adresse ausgeben\n");
printf("-3- Alle Adressen ausgeben\n");
printf("-4- Adressen sortieren\n");
printf("-5- Programm beenden\n");
printf("\nIhre Auswahl : ");
scanf("%d",&auswahl);
/* fflush(stdin); */
getchar();
switch(auswahl) {
case 1 : Eingabe(x++,adressen); break;
case 2 : printf("Anfangsbuchstabe Nachnamen :");
do {
scanf("%c",&c);
} while(getchar()!= '\n');
Suche(adressen,c,x);
break;
case 3 : Ausgabe(adressen,x); break;
case 4 : Sort(adressen,x); break;
default: break;
}
} while(auswahl < 5);
return EXIT_SUCCESS;
}
Dank der neuen Typdefinition
typedef struct adres ADRESSE;
kann auf die Struktur jetzt mit
ADRESSE neueadressen[100];
zugegriffen werden. Dies lässt sich bei längeren Programmen wesentlich einfacher lesen. Vor allem ist dies sinnvoll, wenn mehrere Strukturen vorhanden sind, die einander vom Aufbau sehr ähnlich sind. Die Typdefinition im Programm ließe sich auch noch anders definieren:
typedef struct adres { char vname[20]; char nname[20]; long PLZ; char ort[20]; int geburtsjahr; } ADRESSE; ... ADRESSE adressen[100];
Die Typdefinition kann ebenso auf andere Variablen angewendet werden. Recht häufig sind folgende Definitionen zu sehen:
typedef unsigned char BYTE; // 1 Byte = 8 BIT typedef unsigned int WORD; // 1 WORD = 16 BIT typedef unsigned long DWORD; // 1 DOUBLE WORD = 32 BIT typedef unsigned double QWORD; // 1 QUAD WORD = 64 BIT typedef unsigned int uint; typedef unsigned char uchar;
Zum Beispiel ist danach die folgende Schreibweise
uint wert1, wert2;
äquivalent zu:
unsigned int wert1,wert2;
Das Schlüsselwort typedef wird ebenfalls dazu benutzt, sogenannte primitive Datentypen zu erzeugen. Wozu soll das gut sein? Nehmen wir als Beispiel den primitiven Datentyp uclock_t (primitive Datentypen enden normalerweise immer mit _t). Dieser ist in der Headerdatei <time.h> definiert mit:
typedef long uclock_t;
Auf einem anderen System sieht diese Definition vielleicht so aus:
typedef unsigned int uclock_t;
Die primitiven Datentypen machen ein Programm portabler. Dadurch müssen Sie sich nicht mit den Datentypen bei der Portierung auf andere Systeme auseinandersetzen. Wenn Sie ein Programm beispielsweise auf einem 32-Bit-System programmiert haben und dies anschließend auf einem 16-Bit-System getestet wird, kann die Suche nach dem Fehler einer falschen Werteausgabe frustrierend sein.
Wie schon mit enum oder define wird mit typedef das Programm nicht etwa besser oder schneller, sondern es dient auch hier lediglich dazu, dass sich Ihr Programm besser lesen, schreiben und auf andere Systeme portieren lässt.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.