4 Typen in C
 
 

Damit in C mit Variablen gearbeitet werden kann, muss für diese zunächst Speicherplatz reserviert werden. Dies geschieht, indem dem Variablennamen ein Datentyp zuordnet wird. Neben Variablen besitzen auch Funktionen in C einen Datentyp, der dem Typ des durch die Funktion bereitgestellten Funktionswertes entspricht.

In C wird zwischen Basisdatentypen, deren Modifikationen (durch Voranstellen der Typ-Modifizierer short, long, double, signed und unsigned) und erweiterten Datentypen unterschieden.

Als Basisdatentypen stehen zur Verfügung:
 
 

  1. int : Typ zur Ganzzahldarstellung (z.B. 2, -4, ...),
  1. char : Typ zur Zeichendarstellung (z.B. a, z, M, $, ...) und
  1. float : Typ zur Gleitkommadarstellung (z.B. 1.3, -8.75, 2.45E3, ...)

Der Typ int erlaubt die Anwendung aller Modifizierer. Der Basisdatentyp char lässt sich nur mit den Modifizierern signed und unsigned kombinieren. Auf den Datentyp float lässt sich der Modifizierer long anwenden. Dabei entsteht der Datentyp double (long float), mit dem long nochmals kombiniert werden kann (long double).
 
 

Die Tabelle 8.3 gibt eine Übersicht über die Datentypen, ihren Modifikationen und ihrer Größe im Speicher. Die Größe einiger Datentypen ist dabei abhängig vom verwendeten Computer und kann leicht mit dem sizeof-Operator ermittelt werden.
 
 

Einen Datentyp Boolean, mit dem Wertbelegungen von wahr und falsch möglich wären, gibt es in C nicht. Bei logischen Operationen wird deshalb jeder Wert ungleich Null als wahr und jeder Wert gleich Null als falsch interpretiert.
 
 

Datentyp char

Die char-Vereinbarung wird verwendet um Zeichen abzuspeichern. Der Integer-Wert, der in der Variablen abgespeichert wird, ist dem ASCII-Code zugeordnet. Jede Variable vom Typ char, die in einem arithmetischen Ausdruck steht, wird für die Berechnung automatisch in eine int-Zahl umgewandelt.
 
 

Beispiel:
 
 
 
 

char a;

a = 's';

printf("Der Buchstabe a lautet: %c\n",a);

printf("Der Zahlenwert von a lautet: %d\n",a);
 
 

In der ersten Zeile des Beispiels wird die Variable a als char deklariert. In der zweiten Zeile erfolgt die Initialisierung von a, indem ihm ein Zeichen zugewiesen wird. Das Zeichen muss dafür in einfachen Hochkommas stehen. Mit den beiden printf-Anweisungen wird der Inhalt von a ausgegeben. Die erste Anweisung gibt ein 's' , die zweite gibt die Zahl 115 auf dem Bildschirm aus. Der Grund hierfür liegt darin, das ein Zeichen mit seinem ASCII-Code abgespeichert wird. So kann ohne große Umwandlung der ASCII-Code eines Zeichens abgefragt werden.
 
 

Datentyp int

Zum int-Datentyp zählen : int, unsigned int, long int, unsigned long int, short int und unsigned short int.

Da diese Vereinbarungen für die Maschine am einfachsten zu verarbeiten sind, ergeben sich dadurch sehr kurze Ausführungszeiten bei Rechen- und Zählanweisungen.
 
 

Beispiel:
 
 
 
 

int a, b;

unsigned c;

float d;

long x = 200000000, y;

a = -4; b = 6; d = 12.75;

c = a ;

b = x;
 
 
 
 

Die Variable d wird als 4 Byte große float-Zahl, mit 6 stelliger Genauigkeit definiert. Die als unsigned definierte Variable wird in einen int Typ umgewandelt und kann somit auch negative Werte annehmen. Die Zuweisung b = x; wird vom Compiler nicht als Fehler erkannt, liefert aber ein falsches Ergebnis. Deshalb sollten Zuweisungen zwischen unterschiedlichen Typen grundsätzlich vermieden werden.
 
 

Datentypen float und double

Die Datentypen float und double dienen zur Darstellung von Fließkommazahlen. Dabei steht float für einfache, double für hohe und long double für sehr hohe Genauigkeit. Die Genauigkeit bestimmt, wieviele Dezimalziffern einer Zahl gespeichert werden können. Das heißt, dass bei einer Genauigkeit von 6 Stellen, die beiden Zahlen 12345.6 und 12345.67 nicht unterschieden werden. Das gleiche gilt für die beiden Zahlen 0.000123456 und 0.0001234567.
 
 

Beispiel:
 
 
 
 

float f;

double d;

long double ld= 1.3E1234;
 
 

Das Beispiel zeigt die Deklaration einer float-, double- und long-double-Zahl, wobei letztere mit einem Wert initialisiert wird.

Bei Zuweisungen von einer Variablen zu einer anderen sollten die Typen der beiden Variablen übereinstimmen. Stimmen die beiden Typen nicht überein, so liefert der Compiler meist eine Fehlermeldung oder es wird beim Programmlauf eine Typanpassung durchgeführt. Wird z.B. eine Variable des Typs float oder double einer Variablen vom Typ int zugewiesen, so wird sie in int umgewandelt. Hierbei wird der Nachkommateil der Zahl einfach abgeschnitten.
 
 

Zusammengesetzte Datentypen

Zu den zusammengesetzten Datentypen gehören:

  1. Array
  1. Struktur und
  1. Union

Datentyp Array

Unter einem Array versteht man Folgen von gleichartigen Variablen, die über einen gemeinsamen Namen und über den Arrayauswahloperator [ ] ansprechbar sind. Die einzelnen Elemente eines Arrays haben dabei immer den gleichen Typ.

Häufig verwendete Synonyme für Arrays sind "Vektor" (für eindimensionale Arrays), "Tabelle" und "Datenfeld".

Eindimensionale Arrays

Eindimensionale Arrays besitzen n Elemente in einer Ebene. Die einzelnen Elemente sind von 0 bis (n-1) durchnummeriert. Eine Arraydeklaration lässt sich wie folgt formulieren:

datentyp arrayname[elementanzahl]

Um ein Array zu initialisieren, gibt es drei Möglichkeiten:

  1. bei der Definition,
  1. durch einzelne Zuweisungen oder
  1. mittels Schleife.

Bei der Definition eines Arrays können bereits die entsprechenden Werte in der richtigen Reihenfolge angegeben werden. Die Werte sind dabei von geschweiften Klammern einzuschließen. Der Compiler überprüft, ob die Anzahl der angegebenen Werte mit der Arraygröße übereinstimmt. Sind mehr Werte angegeben, als Elemente vorhanden, gibt der Compiler eine Fehlermeldung aus. Stimmt die Anzahl mit der Arraygröße überein, werden den Elementen die Werte zugewiesen. Ist die Anzahl kleiner, werden alle Elemente, für die kein Wert vorgegeben ist, mit Null initialisiert. Fehlt die Angabe der Elementanzahl bei initialisierten Arrays, so wird sie aus der Anzahl der vorgegebenen Werte berechnet.
 
 

Beispiel:
 
 
 
 

int feld[4]= { 15, -2, 7, -18 };

int feld2[]= { 0, -5, -10 };

int feld3[10];
 
 

In der ersten Zeile wird ein Feld mit einer Arraygröße von 4 Elementen definiert und initialisiert.

In der zweiten Zeile wird ein zweites Feld definiert und initialisiert. Da hier die Angabe über die Größe des Arrays fehlt, wird dies aus der Anzahl der vorgegebenen Werte berechnet.

In der dritten Zeile wird feld3 definiert, ohne jedoch Werte zuzuweisen.

Da es in C keinen Datentyp für Strings gibt, bietet es sich an, dafür ein Array zu deklarieren.
 
 

Beispiel:
 
 
 
 

char name[5]= "anna";

name[0]= 'A';
 
 
 
 

Über den Zuweisungsoperator "=" ist es nur möglich, den Elementen einzelne Zeichen zuzuweisen. Als Abschluss sollte immer ein Ende-Zeichen (Nullbyte) stehen. Die einzelnen Zeichen stehen dabei in einfachen Hochkommas. Soll einem Array im Programm eine ganze Zeichenkette zugewiesen werden, so kann dafür die Funktion strcpy verwendet werden.
 
 

Mehrdimensionale Arrays

Mehrdimensionale Arrays sind eindimensionale Arrays, die als Elemente wieder ein Array enthalten. Die Darstellung mehrdimensionaler Arrays kann folgendermaßen dargestellt werden:

datentyp arrayname [e1] [e2] ... [en]

e1, e2, ... , en geben an, wieviele Elemente in den entsprechenden Dimensionen vorhanden sind.

Die Initialisierung kann wieder über die drei Wege

  1. einzelne Zuweisung,
  1. mittels Schleife oder
  1. bereits bei der Definition erfolgen.
Auf ein Beispiel für die Zuweisung von Werten an einzelne Elemente und die Möglichkeit mit Schleifen wird hier verzichtet, da dies im Wesentlichen wie bei den eindimensionale Arrays gehandhabt wird. Stattdessen sollen an dieser Stelle einige Beispiele für die Zuweisung bei der Deklaration folgen.
 
 

Beispiel:
 
 
 
 

int feld1[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
 
 

int feld2[3][4] = { {0, 1, 2, 3},

{4, 5, 6, 7},

{8, 9, 10, 11}, };
 
 

Wie bei eindimensionalen Arrays ist es auch hier möglich, die Elemente fortlaufend in die geschweiften Klammern zu setzen. Bei einer Tabelle mit wenigen Elementen ist dies noch leicht überschaubar. Steigt die Zahl der Elemente aber, so bietet sich die zweite Variante an, mit der auch feld2 initialisiert wurde. Hier lässt sich leicht ablesen, welche Werte die Elemente der Zeilen und Spalten annehmen.
 
 

Struktur
 
 

Eine Struktur ist eine Folge von einem oder mehreren Elementen, die inhaltlich zusammengehören und über den Strukturnamen und den Elementnamen ansprechbar sind. In der Deklaration einer Struktur muss das Schlüsselwort struct erscheinen. Die einzelnen Elemente einer Struktur müssen nicht vom selben Typ sein, es sind auch komplexere Elemente wie Strukturen oder Arrays als Elemente einer Struktur zugelassen. Um die einzelnen Elemente anzusprechen gibt es zwei Wege. Zum einen kann ein Element über den Punkt (Bezeichner) angesprochen werden. Dazu muss der Name der Struktur und des Elementes, beide durch einen Punkt getrennt, eingegeben werden. Die andere Möglichkeit besteht darin die einzelnen Elemente über den Pfeil (Zeiger) anzusprechen.

Für die Deklaration einer Struktur gibt es verschiedene Möglichkeiten. Hierbei muss zwischen Strukturmuster, das den Aufbau der Struktur angibt und keinen Speicherplatz benötigt, und der eigentlichen Struktur unterschieden werden.

Beispiel 1:
 
 
 
 

struct

{

char nach_name[20];

char vor_name[20];

char strasse[20];

char ort[20];

} adresse;
 
 

strcpy (adresse.nach_name, "Meier");

strcpy (adresse.vor_name, "Emil");
 
 
 
 

In Beispiel 1 wird der Struktur der Name adresse zugewiesen. Über die Funktion strcpy wird dem Element nach_name der Name "Meier" zugeordnet.
 
 

Beispiel 2:
 
 
 
 

/* Ohne Strukturmuster */

struct

{

char name[20];

long verdienst;

} akte; /* Definition einer Struktur akte */
 
 
 
 

Der Struktur wird der Name akte, über den sie dann auch angesprochen wird, zugeordnet.
 
 

Beispiel 3:
 
 
 
 

/* Strukturmuster und Struktur */

struct AKTE

{

char name[20];

long verdienst;

};

struct AKTE akte; /* Definition der Struktur */
 
 

Zunächst wird ein Strukturmuster mit dem Namen AKTE definiert. Durch das Strukturmuster wird kein Speicherplatz belegt; die eigentliche Zuordnung des Strukturnamens erfolgt erst in der letzten Zeile.
 
 

Beispiel 4:
 
 
 
 

struct AKTE

{

char name[20];

long verdienst;

} akte;

Dieses Beispiel zeigt, dass es durchaus möglich ist, ein Strukturmuster zu definieren, und gleichzeitig eine Struktur zu erzeugen.
 
 

Auf die Elemente einer Struktur sind alle Operationen erlaubt, die sonst für normale Datenobjekte gelten.
 
 

Union
 
 

Eine Sonderform des Datentyps Struktur ist der zusammengesetzte Datentyp Verbund oder union. Im Unterschied zum Datentyp Struktur werden hier die Elemente eines Verbundes an ein und der selben Adresse im Speicher abgelegt. Bei der Deklaration einer union braucht deshalb nur soviel Speicher reserviert werden, wie die größte Komponente in Anspruch nimmt.

Verbunde finden dann Anwendung, wenn es darum geht, ein Datenobjekt unter unterschiedlichen Elementnamen anzusprechen. Die Deklaration erfolgt wie die einer Struktur.
 
 

Beispiel:
 
 
 
 

struct

{

char fname[20];

char vname[20];

char strasse[20];

union

{

char plz[4];

char ort[20];

} ortsangabe;

} adresse;

/* Zugriff */ strcpy(adresse.ortsangabe.plz, "01167");

printf("\n%s\n", adresse.ortsangabe.plz);

strcpy(adresse.ortsangabe.ort, "01167 Dresden"); printf("%s\n", adresse.ortsangabe.ort);
 
 
 
 
 
 

Der Zugriff auf einen Verbund erfolgt ebenso wie bei Strukturen über den Punkt bzw. den Pfeil. Der Inhalt von plz ist vollständig in ort enthalten: er belegt die ersten 4 Bytes. Wird der sizeof Operator auf einen Verbund angewandt, so liefert er als Ergebnis den Wert der längsten Komponente.

Für die Deklaration und die zulässigen Operationen eines Verbundes gelten die selben Regeln wie für die Struktur.
 
 
 
 

4.1 Eigene Datentypen
 
 

typedef

Die Programmiersprache C bietet dem Benutzer die Möglichkeit, mit dem Schlüsselwort

typedef eigene Datentypen zu definieren. Die Schaffung solcher eigenen Datentypen dient dabei im Wesentlichen dazu, die Lesbarkeit der Programme zu steigern. Durch das Schlüsselwort typedef werden zunächst Synonyme erzeugt, also gleichbedeutende Datentypen. Diese Synonyme können dann genauso verwendet werden, wie die von C vorgegebenen.

Am häufigsten werden selbstdefinierte Datentypen dazu verwendet, zusammengesetzte Datenstrukturen wie Arrays oder Strukturen zu bezeichnen.
 
 

Beispiel 1:
 
 
 
 

typedef int Ganze_Zahl;

typedef char Zeichen;

Ganze_Zahl a = 12;

Zeichen b;

b = 'e';
 
 
 
 

Im aufgeführten Beispiel werden zunächst die Typen Ganze_Zahl (vom Typ int) und

Zeichen (vom Typ char) definiert. Danach wird die Variable a mit dem Typ Ganze_Zahl vereinbart und mit dem Wert 12 initialisiert. Die Variable b ist vom Typ Zeichen (also char) und erhält in der letzten Zeile das Zeichen 'e'.
 
 

Beispiel 2:
 
 
 
 

typedef struct AKTE

{

char name[20];

long verdienst;

} Meine_Akte;
 
 

Meine_Akte akte;
 
 
 
 

In diesem Beispiel ist die Definition einer Struktur mit Hilfe von typedef aufgezeigt. Zunächst wird das Strukturmuster mit dem Namen Akte erzeugt. Der neue Datentyp bekommt die Bezeichnung Meine_Akte. Im Anschluss daran wird die Struktur akte mit dem neuen Datentyp Meine_Akte deklariert.
 
 

Datentyp enum

Mit dem Schlüsselwort enum lässt sich ein Aufzählungsdatentyp deklarieren. Dieser ermöglicht es, in einer Liste all die Werte aufzuführen, die eine Variable diesen Typs annehmen kann. Dabei werden die Werte nicht als Zahlen, sondern als Namen aufgeführt. Dies hat den Vorteil, das Programme besser lesbar werden.
 
 

Die Definition eines solchen Aufzählungstyps ähnelt der einer Struktur. Zuerst erscheint das Schlüsselwort enum, gefolgt von einem Namen. Die geschweiften Klammern umschließen die Liste. In der Liste können nun Namen aufgeführt werden, denen auch Werte zugewiesen werden können. Fehlen Wertzuweisungen, verteilt der Compiler Werte für die Namen. Begonnen wird bei der 0. Der erste Name bekommt also die 0, der zweite die 1, der dritte die 2 usw. Den Namen wird stets der um 1 erhöhte Wert seines Vorgängers zugewiesen. Der Programmierer kann an jeder beliebigen Stelle eingreifen, und eigene Werte vergeben. Hinter der schließenden geschweiften Klammer kann ein Name für die Variable dieses Aufzählungstyps folgen. Es ist aber auch später möglich, diesem Aufzählungstypen Variablen zuzuweisen.
 
 

Beispiel:
 
 
 
 

enum tag

{

montag = 1,

dienstag,

mittwoch,

donnerstag,

freitag,

sonnabend,

sonntag = 0

};

enum tag wochentag;
 
 
 
 
 
 

In diesem Beispiel wird ein Aufzählungstyp mit dem Namen tag definiert. Die Namen in der Liste werden fortlaufend numeriert. Begonnen wird mit montag, der den Wert 1 zugewiesen bekommt, dienstag den Wert 2, usw. Dem Namen sonntag wird der Wert 0 zugeordnet. In der letzten Zeile wird mit dem Aufzählungstyp tag eine Variable mit dem Namen wochentag vereinbart.

Bei der Wahl der Namen in der Liste ist darauf zu achten, dass alle Namen nur einmal vergeben werden.