Das ATOS-Magazin
 
  zurück zum News-Archiv
Anfang zurück vorwärts Ende 

ANSI C - Ein Programmierkurs - Teil III

Datentypen

In C stehen folgende einfache Datentypen zur Verfügung:

char, short, int, long, float, double

Ein char ist ein Datentyp, der genau ein Zeichen (Buchstaben im Sinne des ASCII-Zeichensatzes) aufnehmen kann. Da C nicht explizit zwischen Zeichen und Zahlen unterscheidet, kann dieser Datentyp auch eine Zahl (in Zeichenform) aufnehmen.

Ein int ist ein Datentyp, der eine ganze Zahl aufnehmen kann, wobei der Wertebereich dem konkreten Computer angepasst ist.

Ein short bzw. long ist eine kurze bzw. lange ganze Zahl.

Es gilt, dass ein short kleiner als ein long ist. Ein int entspricht üblicherweise entweder einem short oder einem long. Es ist in ANSI C nicht definiert, wieviel Bytes diese Datentypen zu belegen haben! Der Wertebereich der einzelnen Datentypen steht in der Datei limits.h. Die Verwendung von Include-Dateien wird später erklärt.

Üblicherweise belegt ein char ein Byte, ein short sind 2 Byte und ein long belegt 4 Byte. Ein int belegt, je nach Compiler, 2 oder 4 Byte. Die Datentypen short, int und long sind vorzeichenbehaftet, bei char ist es implementationsabhängig. Die meisten Compiler sind allerdings konsequent und betrachten char als vorzeichenbehaftet.

Zusätzlich kann durch die Schlüsselworte signed und unsigned vor dem Datentyp explizit angegeben werden, dass der Datentyp vorzeichenbehaftet oder vorzeichenlos ist. Damit vergrößert oder verkleinert sich außerdem der darstellbare Bereich. Mit einem Short, der 16 Bit belegt, kann man den Bereich von -32768 bis 32767 abdecken. Ein unsigned short kann den Bereich von 0 bis 65535 abdecken.

Wertebereiche unterschiedlicher Compiler

Typ TC Sozobon GCC
char 8 Bit 8 Bit 8 Bit
  -128 -128 -128
  127 127 127
short 16 Bit 16 Bit 16 Bit
  -32768 -32768 -32768
  32767 32767 32767
int 16 Bit 16 Bit 32 Bit
  -32768 -32768 -2147483648
  32767 32767 2147483647
long 32 Bit 32 Bit 32 Bit
  -2147483648 -2147483648 -2147483648
  2147483647 2147483647 2147483647

Bei den Datentypen float und double handelt es sich um Fließkommazahlen. Damit lassen sich Kommazahlen wie z.B. Preise darstellen. Aufgrund der speziellen Darstellung der Form 0.aaa * 10bb lassen sich auch sehr große Werte darstellen. Zum Beispiel benutzt TC den IEEE-Standard, der für float den Wertebereich von 10E-38 bis 10E+38 ermöglicht. Es steht aber nicht eine Genauigkeit von 38 Stellen zur Verfügung! Um die Genauigkeit zu erhöhen, gibt es den Datentyp double, der zusätzlich noch einen größeren Wertebereich bietet. Der genaue Wertebereich hängt von der Implementierung des Compilers ab. Der Wertebereich von float kann aus der Includedatei float.h ermittelt werden.

Initialisierung

Es ist möglich, einer Variablen gleich bei der Deklaration einen Wert zuzuweisen, d. h. sie zu initialisieren. Dazu schreibt man hinter der Variablen ein Gleichheitszeichen =, gefolgt von dem gewünschten Wert. Der Wert ist eine Zahlenkonstante. Im nächsten Kapitel wird erklärt, wie Konstanten gebildet werden.

const

Um anzuzeigen, dass sich der Wert einer Variablen nicht ändert, kann sie mit dem Attribut const versehen werden. Dies macht allerdings nur bei einer initialisierten Variablen Sinn.

const double e = 2.71828182845905;
const char ich[] = "Michael Bernstein";

Versucht man den Wert einer const-Variablen zu ändern, ist das Ergebnis implementierungsabhängig.

Konstanten

Wird in C eine ganzzahlige Zahl hingeschrieben, handelt es sich um den Datentyp int, sofern keine weitere Angabe gemacht wird. Beginnt die Zahl mit einer Ziffer ungleich 0 (Null), wird von einer Dezimalzahl ausgegangen. Wenn die erste Ziffer eine 0 (Null) ist, handelt es sich um eine Oktalzahl und wenn die Zahl mit 0x eingeleitet wird, ist es eine Hexadezimalzahl.

Es ist zusätzlich noch möglich, den Datentyp zu spezifizieren. Wenn sich direkt an die Ziffern ein l (kleiner Buchstabe L) oder L (wir erinnern uns: Groß- und Kleinschreibung ist in C signifikant!) anschließt, handelt es sich um eine long-Konstante, ein u oder U steht für eine unsigned-Konstante. Ein ul oder UL kennzeichnet eine unsigned-long-Konstante.

Weiterhin gibt es auch Zeichenkonstanten. Dies sind Zeichen in einfachen Hochkommata wie z.B. 'h' und können jeder ganzzahligen Variable zugewiesen werden. Da jedem Zeichen im ASCII-Code auch eine Nummer zugeordnet ist, kann der Compiler eine Zeichenkonstante auch als Zahl betrachten. Für Zeichen, die nicht darstellbar sind, wie z.B. Steuerzeichen für einen Zeilenvorschub, gibt es zwei Möglichkeiten. Zum einen ist es möglich, mit Hilfe des Backslash '\' als Escapezeichen eine Ersatzdarstellung zu benutzen. Da das '\' eine Ersatzdarstellung einleitet, muss dieses Zeichen selbst auch über eine Ersatzdarstellung eingegeben werden. Weiterhin ist es möglich, über den Backslash '\' und einer Folge von ein bis drei Oktalziffern oder dem Backslash '\' einem 'x' und einer Folge von einer oder mehreren hexadezimalen Ziffern jedes gewünschte Zeichen über seine Ordnungszahl einzugeben. Achtung: welches Zeichen letztendlich auf dem Bildschirm erscheint, hängt dann natürlich auch von dem Zeichensatz ab, den der Computer verwendet. Beispiel: Klingel = '\007'; Bell = '\x7';

Es ist auch möglich, Zeichenkonstanten mit mehr als einem Zeichen zu bilden, z.B. für die Zuweisung an ein short, das ja zwei Byte belegt. Da es aber von der Implementierung abhängt, was der Compiler daraus macht, ist meiner Meinung nach der Nutzen nur sehr eingeschränkt.

Ganze Zeichenketten werden in doppelte Hochkommata eingeschlossen. Es gibt in C keinen eigenen Datentyp für Zeichenketten. Im Kapitel Felder wird erklärt, wie man dennoch Zeichenketten in C benutzt.

Boolesche Werte gibt es nicht in C. Ein Wert einer ganzzahligen Variablen von ungleich 0 entspricht einem TRUE, ein Wert von 0 (Null) entspricht einem FALSE. Wir werden bei der Besprechung von Kontrollstrukturen nochmals darauf zurückkommen.

Konstanten vom Typ float oder double kann man, wie man es von reellen Zahlen gewohnt ist, in der Kommadarstellung schreiben, wobei anstelle des Kommas der in den USA gebräuchliche Punkt tritt. Dies sieht dann so aus: 3.14159. Zusätzlich gibt es für sehr kleine oder sehr große Zahlen die wissenschaftliche Darstellung: 34.57E12, was für 34,57 * 1012 steht oder 1.456E-23, was für 1,456 * 10-23 bzw. 1 / (1,456 * 1023 ) steht.

Typkonvertierung

C kann implizit von einem kleineren in einen größeren Datentyp umwandeln. Wenn z.B. einer int-Variablen eine char-Variable zugewiesen wird, kann C automatisch char zu int konvertieren, da der Wertebereich von char in den Wertebereich von int paßt. Auch bei Verknüpfungen in Anweisungen kann diese Konvertierung automatisch erfolgen. Werden z.B. ein int und ein char addiert und einem int zugewiesen, so wird der char automatisch zu einem int konvertiert.

In anderen Fällen, also bei einer Typumwandlung zu einem kleineren Datentyp, muss dem Compiler dies explizit angegeben werden. Dazu dient der cast. Der gewünschte Datentyp wird in Klammern der Variable oder Konstante oder auch einem gesamten Ausdruck vorangestellt.

...
int i = 10;
char j;

j = (char)i;

Die Variable i wird zu einem char gecastet, um sie j zuweisen zu können.

Hierbei muss der Anwender selbst darauf achten, dass der Ergebnisdatentyp auch den kompletten Wert aufnehmen kann. Wird der Wertebereich des Ziels überschritten, kann ein Overflow zu negativen Zahlen auftreten, wenn das Ziel vorzeichenbehaftet ist. Achtung: beim Datentyp char ist nicht definiert, ob er vorzeichenbehaftet oder vorzeichenlos ist!

Schreiben Sie ruhig ein paar kleine Testprogramme, nachdem Sie auch das Kapitel über Anweisungen durchgelesen haben, um sich das Verhalten zu verdeutlichen. Benutzen Sie auch Werte, die den Wertebereich des Ziels überschreiten.

Beispiele für Deklarationen

Wie sieht das Ganze jetzt aus? Dazu folgt ein Miniprogramm, das einfach mal ein paar Variablen deklariert.

char taste;

int main()
{
   int i=0, lauf_index;
   unsigned long anzahl_tests;
}

Gültigkeitsbereich

Eine Variable auf globaler Ebene, also außerhalb einer Funktion, ist in allen Funktionen darunter bekannt, eine Variable innerhalb eines Blockes jedoch nur innerhalb des Blocks, in dem sie deklariert wurde. Innerhalb einer Ebene kann es keine zwei Bezeichner mit dem gleichen Namen geben. Eine Variable innerhalb eines Blocks überdeckt andere Variable gleichen Namens außerhalb.

Damit das Ganze etwas anschaulicher wird und weil schon genug Theorie kam, folgen hierzu einige Beispiele. Testen Sie ruhig alle Beispiele; erst durch eigenes Probieren kommt die nötige Anschauung. Und mit Anschauung kann man sich Dinge leichter merken.

Was passiert bei folgendem Beispiel?

#include <stdio.h>
 
int i=3;
int main()
{
   printf("i = %d\n",i);
}
int i;

Tja, da hier zweimal die Variable i deklariert ist, beschwert sich schon der Compiler und das Programm lässt sich nicht übersetzen.

Was passiert bei folgendem Beispiel?

#include <stdio.h>
 
float main=3.5;
int main()
{
   printf("main = %d\n",main);
}

Auch hier beschwert sich der Compiler. Denn hier haben wir den Namen main zweimal vergeben.

Was passiert bei folgendem Beispiel?

#include <stdio.h>

int i=10;
int main()
{  int i=15;
   printf("i = %d\n",i);
}

Dieses Beispiel sollte sich problemlos übersetzen lassen. Die Ausgabe des Programms ist i = 15. Innerhalb der Funktion main wird die mit 15 initialisierte Variable benutzt. Die global deklarierte und mit 10 initialisierte Variable i ist innerhalb von main unsichtbar, da sie von der inneren Variablen desselben Namens überdeckt wird.

Was passiert bei folgendem Beispiel?

#include <stdio.h>

int i=3;
int main()
{
   printf("j = %d\n",j);
}
int j=5;

Hier sollte sich wieder der Compiler beschweren. Eine globale Variable ist in allen darunter liegenden Funktionen bekannt. Die Funktion main liegt aber über der Deklaration von j und damit kennt main j nicht.

Im nächsten Teil werden wir uns mit Speicherklassen beschäftigen.

Michael Bernstein


Anfang zurück vorwärts Ende  Seitenanfang

Copyright und alle Rechte beim ATOS-Magazin. Nachdruck und Veröffentlichung von Inhalten nur mit schriftlicher Zustimmung der Redaktion.
Impressum - Rückmeldung via Mail oder Formular - Nachricht an webmaster