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

ANSI C - Ein Programmierkurs - Teil II

Compiler

Als erste Übung werden wir die Entwicklungsumgebungen in Betrieb nehmen und konfigurieren. Dies unterscheidet sich sehr stark, je nach verwendetem Compiler und verwendeter Shell. Sozobon und GCC ähneln sich etwas, da beide Kommandozeilenprogramme sind, und die unbedingt notwendigen Parameter identisch sind.

Die Konfiguration für Turbo-C/Pure-C (TC/PC) bzw. weitere Kommandozeilenparameter für Sozobon und GCC werden im Anhang nochmals detaillierter ausgeführt. Hier werden nur die unbedingt notwendigen Einstellungen besprochen.

Als Beispielprogramm ist folgendes Programm einzugeben und unter dem Namen first.c zu speichern. Es ist der Klassiker der C-Programmierung; sehr viele C-Kurse bzw. Bücher beginnen mit diesem Programm.

Achtung! Nach der letzten Zeile ist noch einmal ein Zeilenumbruch (RETURN-Taste drücken) erforderlich, damit der Sozobon-Compiler das Programm akzeptiert.

first.c

#include <stdio.h>

int main(void)
{
   printf("Hallo Welt!");
   return 0;
}

TC/PC

Der Inhalt der Disketten ist in ein beliebiges Verzeichnis zu kopieren, z.B. c:\tc bzw. c:\pc. In diesem Verzeichnis sollten unter anderem die 2 Verzeichnisse include und lib zu finden sein; außerdem tc.prg, tc.cfg bzw. pc.prg, pc.cfg und default.prj. Im Verzeichnis include befinden sich Dateien mit der Extension .h, im Verzeichnis lib befinden sich Dateien mit der Extension .lib sowie die Datei tcstart.o bzw. pcstart.o. Die Bedeutung dieser Dateien wird später erklärt.

Dies sind auch die Dateien, die für ein Minimalsystem auf Diskette unbedingt erforderlich sind.

Konfiguration

Als nächstes muss das System konfiguriert werden. Die hier abgebildeten Dialoge gehören zu TC. Die entsprechenden Dialoge von PC unterscheiden sich nur minimal, die wesentlichen Einträge sind auch unter PC vorhanden.

Unter Options im Menüpunkt Compiler erscheint folgender Dialog:

[Bild]

Hier muss das include directory auf den entsprechenden Pfad gesetzt werden. Das wäre im obigen Beispiel: c:\tc\include

Unter Options im Menüpunkt Linker erscheint ein Dialog für die Linkeroptionen:

[Bild]

Hier muss das library directory auf den entsprechenden Pfad gesetzt werden. Das wäre im obigen Beispiel: c:\tc\lib

Anschließend bitte nicht das Abspeichern vergessen; dazu unter Options den Menüpunkt save TC.CFG aufrufen.

Jetzt kann unter File mit dem Menüpunkt Open C mit dem Fileselektor eine neue Datei angelegt und editiert werden. Unter Project mit dem Menüpunkt Run kann diese Datei übersetzt und sofort ausgeführt werden.

[Bild]

Jetzt sollte normalerweise der Compiler das Programm übersetzen, der Linker diese Datei mit den dazu benötigten Bibliotheken zusammenbinden und anschließend das Programm ausgeführt werden. TC/PC öffnet ein neues Fenster, in dem jetzt nur eine Meldung des Linkers erscheint. Sollten auch Fehlermeldungen des Compilers erscheinen, ist das Programm fehlerhaft abgetippt worden und sollte auf Tippfehler untersucht werden. Meldungen über doppelt definierte Symbole, die der Linker ausgibt, können hier ignoriert werden.

Da sowohl Compiler als auch Linker vor Ausgabe der Meldungen eine Überschrift wie ******* Compiler messages: ausgeben, können die Meldungen eindeutig zugeordnet werden. Mit der Taste Esc kann der Bildschirm auf die Ausgabe des Programms umgeschaltet werden. Diese Umschaltung funktioniert allerdings nur in den Standardauflösungen und nicht mit Grafikkarten. Auch Shells oder Multitasking-Betriebssysteme mit einem eigenen Konsolenfenster könnten die Ausgabe beeinflussen.

Wenn es Probleme gibt, die Ausgabe des Programms zu lesen, kann das Programm wie folgt erweitert werden. Es wartet damit vor der Beendigung darauf, dass der Benutzer die Returntaste drückt.

Wartendes first.c

#include <stdio.h>

int main(void)
{
   printf("Hallo Welt!");
   getchar();
   return 0;
}

Sozobon

Der Inhalt der Archive ist in ein beliebiges Verzeichnis zu entpacken, z.B. c:\sozobon. Die Dateien des Archivs scbin20.lzh (cc.ttp, ...) gehören in das Unterverzeichnis bin. Hier sind die ausführbaren Programme zu finden. Achtung: Wird die Pfadangabe des Archivs übernommen, dann wird ein Verzeichnis scbin20 angelegt, das die Programme enthält. Dieses Verzeichnis kann in bin umbenannt, oder der Inhalt kopiert werden.

Das Archiv sozlib15.zip enthält die Bibliotheken. Nach dem Auspacken findet man ein Verzeichnis sozdistr vor. Dessen Inhalt ist in das gewünschte Verzeichnis, hier c:\sozobon, für Sozobon zu kopieren.

Das Gleiche ist mit sozuti09.zip durchzuführen. Hier sind noch einige Hilfsprogramme enthalten. Das darin befindliche make.ttp wird benötigt, wenn das Projekt auf mehrere Dateien aufgeteilt wird.

Als nächstes muss das Environment gesetzt werden, damit der Compiler die Includedateien, den Linker, und der Linker die Bibliotheken findet. Folgende Variablen sind zu setzen:

LIB
INCLUDE
PATH
TEMP

Für die Shell Guläm ist unten ein Skript vorgestellt, das dies erledigt. Die dort aufgeführten Pfade müssen noch auf das Verzeichnis von Sozobon auf dem eigenen System angepasst werden. Die Pfade für das Include- und das Libverzeichnis gelten so für den Sozobon-Compiler auf der Seidel SDK-CD bzw. den oben angegebenen Quellen. Sollte sich die verwendete Distribution hier unterscheiden, so sind die Pfade entsprechend anzupassen.

Im Includeverzeichnis muss eine größere Zahl von Dateien mit der Extension .h zu finden sein, darunter auch stdio.h. In dem Libverzeichnis sind unter anderen crt0.o und eine Anzahl Dateien mit der Extension .a zu finden.

Es ist auch möglich, die Verzeichnisnamen aus den Archiven direkt zu benutzen und das Environment entsprechend anzupassen.

Das Programm wird mit folgender Kommandozeile übersetzt:

cc -o first.tos first.c

Es sollte keine weitere Meldung auf dem Monitor erscheinen. Anschließend sollte in dem Verzeichnis, in dem first.c steht, das übersetzte Programm first.tos stehen.

Wenn von Guläm die Fehlermeldung kommt, dass der Befehl cc nicht gefunden wurde, stimmt entweder der Wert der Environmentvariable PATH nicht oder es wurde versäumt, mit dem Befehl rehash Guläm anzuweisen, die Verzeichnisse der PATH-Variable nach ausführbaren Programmen zu scannen.

Wenn vom Compiler die Fehlermeldung erscheint, dass die Includedatei stdio.h nicht gefunden wurde, stimmt der Wert für INCLUDE nicht.

Genauso ist bei der Fehlermeldung des Linkers, dass er crt0.o oder eine Lib nicht gefunden habe, die Variable LIB zu prüfen.

sozobon.g

setenv LIB c:\sozobon\lib\sozobonx\xdlibs
setenv INCLUDE c:\sozobon\include\xdlibs
setenv PATH c:\sozobon\bin
setenv TEMP c:\temp
rehash

GCC

Der Inhalt der Archive ist in ein beliebiges Verzeichnis zu entpacken, z.B. c:\gnu. Der Inhalt der Archive gcc258ba.zoo und gcc258bb.zoo wird in das Unterverzeichnis bin entpackt.

Der Inhalt des Archivs includ97.zoo gehört in das Verzeichnis include. Die Dateien, die in diesem Archiv im Verzeichnis sys sind, gehören natürlich nach include\sys.

Der Inhalt des Archivs libolb97.zoo kommt in das Verzeichnis lib. Als nächstes muss das Environment gesetzt werden, damit der Compiler die Includedateien, den Linker, und der Linker die Bibliotheken findet. Folgende Variablen sind zu setzen:

GNULIB
GNUINC
PATH
TEMP

Für den C++-Compiler müssen noch zusätzlich folgende Variablen gesetzt werden:

GXXINC und GXXLIB

Für die Shell Guläm ist unten ein Skript vorgestellt, dass dies erledigt. Die dort aufgeführten Pfade müssen noch auf das Verzeichnis von GCC auf dem eigenen System angepasst werden. In dem Includeverzeichnis muss eine größere Zahl von Dateien mit der Extension .h zu finden sein, darunter auch stdio.h. In dem Libverzeichnis sind unter anderen crt0.o und eine Anzahl Dateien mit der Extension .olb zu finden.

Das Programm wird mit folgender Kommandozeile übersetzt:

gcc -o first.tos first.c

Es sollte keine weitere Meldung auf dem Monitor erscheinen. Anschließend sollte in dem Verzeichnis, in dem first.c steht, das übersetzte Programm first.tos stehen.

Wenn von Guläm die Fehlermeldung kommt, dass der Befehl gcc nicht gefunden wurde, stimmt entweder der Wert der Environmentvariable PATH nicht, oder es wurde versäumt, mit dem Befehl rehash Guläm anzuweisen, die Verzeichnisse der PATH-Variable nach ausführbaren Programmen zu scannen.

Wenn vom Compiler die Fehlermeldung erscheint, dass die Includedatei stdio.h nicht gefunden wurde, stimmt der Wert für GNUINC nicht.

Genauso ist bei der Fehlermeldung des Linkers, dass er crt0.o oder gnu.olb nicht gefunden habe, die Variable GNULIB zu prüfen.

gnu.g

setenv GNULIB c:\gnu\lib
setenv GNUINC c:\gnu\include
setenv GCC_EXEC_PREFIX c:\gnu\bin\gcc-
setenv UNIXMODE .,/d
set path c:\gnu\bin,$path
setenv TEMP c:\temp
setenv TMPDIR c:\temp
rehash

Packer/Entpacker

Hier folgt eine Kurzanleitung zum Auspacken der Archive. Sie ersetzt nicht die Anleitung der entsprechenden Programme.

Die beiden Programme lzhshell und stzip sind jeweils GEM-Programme und deshalb selbsterklärend. Die Programme zoo, gzip und tar sollten als Kommandozeilenprogramme von einem Kommandozeileninterpreter (shell) gestartet werden. Es ist aber ausreichend, die Entpacker in das Verzeichnis des Archivs zu kopieren und nach einem Doppelklick die Parameter in den Dialog des Desktops einzugeben.

Die zoo-Archive werden mit folgender Befehlszeile ausgepackt:

zoo -extract <archiv.zoo>

Die tgz-Archive sind tar-Archive, die anschließend mit gzip gepackt wurden. Sie müssen also zuerst mit gzip ausgepackt, und anschließend die Dateien aus dem Archiv herausgeholt werden. Dazu werden zwei Programme gestartet. Zuerst wird das Archiv dekomprimiert:

gzip -d <archiv.tgz>

Anschließend werden die Dateien aus dem Archiv herausgeholt:

tar xf <archiv.tar>

Anmerkung: bei neueren Versionen von tar lassen sich die beiden Schritte Entpacken und Auspacken auch in einem einzigen Schritt erledigen (nämlich dann, wenn tar die Option z versteht):

tar xzf <archiv.tgz>

Struktur eines C-Programms

Schauen wir uns mal das (leicht erweiterte) Beispiel an. Diese Datei besteht aus verschiedenen Bereichen. Bei den Zeilen mit einem # in der ersten Spalte handelt es sich um Anweisungen für den Präprozessor. Darunter befinden sich eine Deklaration einer Variablen und im Anschluss daran eine Funktion. Ein gültiges C-Programm muss mindestens eine Funktion mit dem Namen main enthalten! Die Reihenfolge, in der Funktionen, Deklarationen und Präprozessoranweisungen erscheinen, ist beliebig, wichtig ist nur der Gültigkeitsbereich. Sie können auch mehrfach vorhanden sein oder entfallen, wenn sie nicht benötigt werden. Unser Beispiel first.c, das dazu diente, die Compiler in Betrieb zu nehmen, hatte keine Deklarationen. Um sich schneller in fremde Programme einzuarbeiten, wird meist die unten aufgeführte Reihenfolge bevorzugt.

#include <stdio.h>              |- Präprozessoranweisungen
                                 /
                                 \ 
 int i;                          |- Deklarationen von Datentypen
                                 |  und Variablen
                                 /
 int main(void)                  \ 
 {                               |
    int i; /* als Beispiel */    |
                                 |- Funktionen
    printf("Hallo Welt!");       |
    return 0;                    |
 }                               /

Der in /* und */ eingeschlossene Text ist ein Kommentar, der vom Compiler überlesen wird. Kommentare dienen nur dazu, einem Programmierer Hinweise o.ä. zu geben. Sie können damit zum Verständnis von Programmen beitragen oder aber Teile des Codes von der Übersetzung ausnehmen.

Einrückungen o.ä. sind nicht relevant und dienen nur dazu, dass der Programmierer optisch die Struktur des Programms leichter erfasst. Das obige Programm ließe sich deshalb z.B. auch wie folgt schreiben:

#include <stdio.h>
int i;
int main(void) {int i;printf(Hallo Welt!);return 0;}

Durch Einfügen von Whitespaces, also Leerzeichen, Tabulatoren und Zeilenvorschübe, wird ein Programm lesbarer formatiert. Dazu wird jeder Block innerhalb geschweifter Klammern eingerückt. Eine gute Größe sind drei Leerzeichen, da hierbei noch nicht zu viel Platz einer Zeile verloren geht. Wenn auch die Monitore immer größer werden, so beschränkt man sich doch häufig auf maximal 80 Zeichen pro Zeile, damit auch bei einem Ausdruck die Zeile komplett auf das Papier passt und nicht vom Drucker umbrochen werden muss.

Die Funktion kann man auch weiter aufschlüsseln. Sie besteht aus einem Funktionskopf und einem Block in geschweiften Klammern. Dieser Block kann am Blockanfang Deklarationen und anschließend Anweisungen (bzw. Statements auf Neudeutsch) enthalten.

int main(void)                  |- Funktionskopf
{                               \ 
   int i;                       |- Deklarationen
                                /
   printf(Hallo Welt!);       \ 
   return 0;                    |- Anweisungen / Statements
}                               /

In den folgenden Kapiteln werden wir uns die einzelnen Teile genauer anschauen. Zuerst kommt etwas Theorie über Variablen und Datentypen. Anschließend können mit Anweisungen erste Übungen mit Programmen durchgeführt werden.

Nicht jedes der Beispiele wird ein komplettes Programm sein. Solche Beispiele werden dadurch gekennzeichnet, dass in ihnen 3 Punkte (...) als Hinweis auf fehlende Teile auftauchen. Solche Beispiele müssen Sie dann selbst in die Funktion main einbauen. Die benutzten Variablen sind auch zu deklarieren und auf sinnvolle Werte zu setzen, wenn noch keine Deklarationen vorhanden sind. Die letzte Zeile return 0; der Funktion main aus dem oben aufgeführten Beispiel ist immer mit zu übernehmen, wenn ein unvollständiges Beispiel in ein Programm übernommen wird. Andernfalls erhält man eine entsprechende Meldung des Compilers.

Ist in dem Beispiel eine Ausgabe (printf) enthalten, muss die Zeile include <stdio.h> auch mit übernommen werden. Ansonsten kann sie wegfallen.

Wenn die Beispiele übersetzt werden, können noch Warnungen des Compilers auftreten, weil z.B. Variablen nicht weiter benutzt werden. Sie können hier ignoriert werden, da eine Abhilfe das Programm nur unnötig vergrößern würde und das Wesentliche des Beispiels verschleiert. Bei der Entwicklung eigener Programme sollte man allerdings auch auf Warnungen ein Augenmerk richten, da es sich um versteckte Fehler handeln kann.

Variablen und Standarddatentypen

In C muss jede Variable durch die Angabe ihres Datentyps und Namens deklariert werden. Der Compiler kennt keine impliziten Variablen. Dies mag einem Basic-Programmierer vielleicht etwas umständlich erscheinen. Der Vorteil ist aber, dass gerade bei Verwendung von aussagekräftigen Namen ein Tippfehler zu einem ungültigen Namen führt und damit schon vom Compiler erkannt wird.

Variablen können außerhalb von Funktionen an jeder Beliebigen Stelle und am Anfang eines jeden Blocks (geschweifte Klammern) deklariert werden.

Gültige Namen

Ein in C gültiger Name besteht nur aus Buchstaben, Ziffern und dem Unterstrich '_', wobei zwischen Groß- und Kleinschreibung unterschieden wird.

Das erste Zeichen muss ein Buchstabe sein. Die deutschen Umlaute werden nicht zu den Buchstaben gezählt, hier sind nur 'a' - 'z' und 'A' - 'Z' erlaubt! Es werden mindestens die ersten 31 Zeichen für eine Unterscheidung der Namen herangezogen. Bei Namen, die aus anderen Bibliotheken stammen, können es aber weniger Zeichen sein; dann sind mindestens 6 Zeichen signifikant. Es muss hier auch nicht zwingend zwischen Groß- und Kleinschreibung unterschieden werden.

Einige Namen sind von der Sprache C schon reserviert und dürfen nicht für eigenen Namen benutzt werden. Diese reservierten Wörter sind im Kapitel reservierte Bezeichner aufgeführt.

Einige Beispiele für gültige Namen:

Name1 Test DiesIstEinSprechenderName dies_auch _Nur_intern Zeile_3
Dies_ist_ein_sehr_langer_Namen_mit_vielen_Buchstaben
Dies_ist_ein_sehr_langer_Namen_auch_mit_vielen_Buchstaben

Die beiden letzten Namen unterscheiden sich in den ersten 31 Zeichen nicht. Ein Compiler, der sich nur an das Minimum von mindestens 31 signifikanten Zeichen hält, kann diese beide Namen also nicht unterscheiden.

Einige Beispiele für unzulässige Namen:

3_Zeichen Häuser while

Es hat sich als Konvention eingebürgert, für Variablenbezeichner Kleinschreibung zu benutzen. Wenn ein Name aus mehreren Worten zusammengesetzt ist, werden die einzelnen Bestandteile durch einen Unterstrich voneinander abgetrennt:

dies_ist_ein_zusammengesetzter_name

Man sollte außerdem einen Namen wählen, der für die Verwendung der Variable aussagekräftig ist, also einen sprechenden Namen. Dies erleichtert es, die Verwendung der Variablen zu erkennen und damit ein Programm zu verstehen!

Im nächsten Abschnitt werden wir uns mit Datenstrukturen 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