vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Woche 1

Tag 1

Einführung in Linux und die Programmiersprac he C

Willkommen zu »C-Programmierung für Linux in 21 Tagen«. Die heutige Lektion bildet den Einstieg für alle zukünftigen Experten auf diesem Gebiet. Heute lernen Sie:

Warum C?

Heutzutage steht in der Welt der Computerprogrammierung eine Vielzahl höherer Programmiersprachen zur Auswahl, zum Beispiel C, C++, Perl, Python, Tcl/Tk, BASIC und Java. Alles ohne Zweifel ausgezeichnete Programmiersprachen, die mit den meisten Programmieraufgaben spielend fertig werden. Trotzdem gibt es einige Gründe, warum professionelle Programmierer C bevorzugen:

Wie diese Punkte zeigen, ist C eine ausgezeichnete Wahl für den Programmieranfänger. Wie steht es jedoch mit C++? Vielleicht haben Sie bereits von C++ und der damit verbundenen Programmiertechnik der objektorientierten Programmierung gehört. Vielleicht fragen Sie sich, wo die Unterschiede zwischen C und C++ liegen und ob Sie nicht C++ anstelle von C lernen sollten.

Glücklicherweise brauchen Sie sich darüber nicht den Kopf zu zerbrechen. C++ ist eine Obermenge von C, womit ich sagen will, dass C++ alles von C enthält plus einigen Zusätzen für die objektorientierte Programmierung. Für jemanden, der das Programmieren erst lernen will, ist es sicherlich von Vorteil, eine kleine, relativ einfache Sprache wie C zu erlernen statt einer großen, komplexen Sprache wie C++. Wenn Sie sich anschließend dem Studium von C++ widmen, lässt sich fast alles, was Sie zu C gelernt haben, auf die Obermenge C++ übertragen. Wer C lernt, lernt nicht nur eine der mächtigsten und populärsten Programmiersprachen, sondern bereitet sich damit auch auf die objektorientierte Programmierung vor.

Eine weitere Programmiersprache, die immer mehr in den Mittelpunkt rückt, ist Java. Java basiert auf C++, das wiederum auf C basiert. Wenn Sie sich später entscheiden sollten, Java zu lernen, werden Sie feststellen, dass fast alles, was Sie zu C gelernt haben, auch für Java gilt.

Kurzer geschichtlicher Abriss der Programmiersprache C

Die Programmiersprache C wurde 1972 von Dennis Ritchie in den Bell Telephone Laboratories entwickelt. Das Ziel dieser Sprache war es, die Programmierung des Unix-Betriebssystems zu erleichtern und von der Assembler-Sprache wegzukommen. Außerdem wurde es dadurch wesentlich leichter, Programme zwischen Computern mit unterschiedlicher Hardware auszutauschen.

Ihre Leistungsfähigkeit und Flexibilität machte C schnell auch außerhalb der Bell- Labore bekannt. Überall begannen Programmierer damit, die verschiedensten Programme aufzusetzen. Bald jedoch entwickelten unterschiedliche Organisationen ihre eigenen C-Versionen, und die feinen Unterschiede zwischen den Implementierungen bereiteten den Programmierern nicht selten großes Kopfzerbrechen. Zur Lösung dieses Problems richtete das amerikanische Normungsinstitut (American National Standards Institute ANSI) 1983 ein Komitee ein, das eine Standarddefinition von C erarbeiten sollte, die dann als ANSI-C- Standard bekannt wurde. Etwas später, in den frühen 90ern, gab die internationale Normungsbehörde (International Standards Organization, ISO) einen neuen Standard heraus, der auch international anerkannt wurde. Mit wenigen Ausnahmen entspricht jeder moderne C-Compiler diesen Standards.

Die Programmiersprache C heißt C, da ihr Vorläufer B genannt wurde. Die Programmiersprache B wurde von Ken Thompson, ebenfalls an den Bell Laboratories, entwickelt. Es dürfte Ihnen nicht schwer fallen, zu raten, warum sie B heißt.

Erste Schritte vor der Programmierung

Programme lösen Probleme. Sie können nicht alle Probleme lösen, aber sie können computerbezogene Probleme lösen. Wenn Sie durch das World Wide Web surfen wollen, gibt es ein Programm, den so genannten Webbrowser, der dieses Problem für Sie löst. Dies ist ein konkretes Problem mit einer konkreten Lösung - einem Webbrowser. Zu anderen computerbezogenen Problemen gibt es vielleicht keine oder nicht so optimale Lösungen. Bleiben wir beim Beispiel des Webbrowsers. Vielleicht ist Ihnen zu dem Webbrowser noch ein Verbesserungsvorschlag eingefallen, den Sie gerne implementiert sähen. Damit hätten Sie ein Programmierproblem zu lösen.

Um das Programmierproblem zu lösen, sollten Sie schrittweise vorgehen. Zuerst müssen Sie das Problem definieren. Wenn Sie das Problem nicht kennen, können Sie auch keine Lösung dafür finden! Erst wenn Sie das Problem umrissen haben, können Sie überlegen, wie es zu beheben ist. Sobald Sie einen Plan haben, können Sie diesen in der Regel auch implementieren. Ist der Plan implementiert, müssen Sie die Ergebnisse überprüfen, um festzustellen, ob damit das Problem gelöst wurde. Diese Logik lässt sich auf viele Bereiche übertragen einschließlich der Programmierung.

Wenn Sie ein Programm in C (oder einer anderen Programmiersprache) erstellen, sollten Ihre Schritte ungefähr wie folgt aussehen:

  1. Legen Sie das Ziel des Programms fest.
  2. Eruieren Sie die Hilfsmittel, die Sie zur Erstellung des Programms verwenden wollen.
  3. Schreiben Sie das Programm, um das Problem zu lösen.
  4. Führen Sie das Programm aus, um die Ergebnisse zu testen.

Ein Beispiel für ein mögliches Ziel (siehe Schritt 1) wäre die Entwicklung eines Textverarbeitungssystems oder eines Datenbankprogramms. Eine wesentlich einfachere Zielsetzung ist es, Ihren Namen auf dem Bildschirm auszugeben. Wenn Sie keine Zielvorstellung hätten, würden Sie kein Programm schreiben, deshalb ist der erste Schritt bereits getan.

Als zweiten Schritt sollten Sie die Hilfsmittel bestimmen, die Sie für die Erstellung des Programms benötigen. Benötigen Sie zur Lösung des Problems ein Computerprogramm? Welche Informationen müssen berücksichtigt werden? Welche Formeln sollen verwendet werden? Während dieses Schrittes sollten Sie versuchen festzulegen, was Sie an Wissen benötigen und in welcher Reihenfolge die Lösung implementiert werden soll.

Lassen Sie uns ein Beispiel betrachten. Angenommen jemand bittet Sie, ein Programm zu schreiben, das die Fläche eines Kreises ermittelt. Schritt 1 ist damit erledigt, da Sie das Ziel vor Augen haben: die Fläche eines Kreises berechnen. Schritt 2 besteht darin, festzulegen, was Sie wissen müssen, um die Fläche zu bestimmen. Gehen wir in diesem Beispiel davon aus, dass der Benutzer dieses Programms Ihnen den Radius des Kreises mitteilt. Mit diesem Wissen können Sie die Formel pi*r^2 anwenden, um die Antwort zu erhalten. Damit haben Sie alles Notwendige, um mit den Schritten 3 und 4 fortzufahren, die auch als Programmentwicklungszyklus bezeichnet werden.

Der Zyklus der Programmentwicklung

Der Zyklus der Programmentwicklung teilt sich wiederum in verschiedene Schritte auf. Der erste Schritt besteht darin, dass Sie mit einem Text-Editor eine Datei erstellen, die den Quellcode enthält. Im zweiten Schritt kompilieren Sie diesen Quellcode, um eine ausführbare Datei zu erzeugen. Als dritten Schritt führen Sie das Programm aus, um festzustellen, ob es wie geplant funktioniert.

Der Entwicklungszyklus in C

Schritt 1 Setzen Sie Ihren Quellcode mit Hilfe eines Text-Editors auf. In der Regel haben Quellcode-Dateien in C die Extension .c (zum Beispiel meinprog.c, datenbank.c).

Schritt 2 Kompilieren Sie das Programm mit einem Compiler. Wenn der Compiler keine Fehler feststellt, wird die Datei gelinkt und eine ausführbare Datei erstellt. Fahren Sie dann mit Schritt 3 fort. Enthält Ihr Programm Fehler, müssen Sie zurück zu Schritt 1 und diese erst beheben.

Schritt 3 Führen Sie das Programm aus. Sie sollten sich anhand von Tests vergewissern, dass das Programm erwartungsgemäß funktioniert. Wenn nicht, beginnen Sie wieder bei Schritt 1 und nehmen die entsprechenden Änderungen oder Erweiterungen an Ihrem Quelltext vor.

Abbildung 1.1 veranschaulicht die Schritte der Programmentwicklung. Normalerweise werden Sie diese Schritte mehrmals durchlaufen, bevor Sie Ihr Programm beenden, es sei denn, Sie haben ein extrem einfaches Programm; denn selbst erfahrene Programmierer können sich nicht einfach hinsetzen und ein vollständiges und absolut fehlerfreies Programm in nur einem Durchgang schreiben. Da dieser Entwicklungszyklus (Bearbeiten-Kompilieren-Linken-Testen) mehrmals durchlaufen wird, ist es wichtig, sich mit den dafür notwendigen Werkzeugen vertraut zu machen - dem Text-Editor und dem Compiler gcc.

Abbildung 1.1:  Die Schritte der C-Programmentwicklung.

Die Entwicklungswerkzeuge

Um C-Programme unter Linux zu schreiben, benötigen Sie zusätzliche Programme, die wahrscheinlich schon auf Ihrem Rechner installiert sind. Dazu gehören ein Text- Editor, ein C-Compiler und Tools wie das make-Programm und Debugger. Was genau davon verfügbar ist, untersuchen wir, wenn wir die jeweiligen Tools einsetzen.

Auf vielen anderen Systemen wie Apple Macintosh und Microsoft Windows werden inzwischen so genannte integrierte Entwicklungsumgebungen (abgekürzt IDE, für Integrated Development Environment) eingesetzt, die Text-Editor, Compiler und weitere Tools in sich vereinen. Seit 1999 gibt es solche integrierten Entwicklungsumgebungen auch für Linux, doch die große Mehrheit der Linux-Programmierer verwendet weiterhin separate Tools.

Quellcode erzeugen

Der Quellcode besteht aus einer Reihe von Anweisungen oder Befehlen, die bewirken, dass der Computer die von Ihnen gewünschten Aufgaben erledigt. Wie bereits erwähnt, besteht der erste Schritt im Zyklus der Programmentwicklung darin, den Quellcode in einen Text-Editor einzugeben. Nehmen wir zum Beispiel die folgende Zeile C-Code:

printf("Hallo, Mama!");

Diese Anweisung teilt dem Computer mit, dass er die Nachricht »Hallo, Mama!« auf dem Bildschirm anzeigen soll. (Wie diese Anweisung genau funktioniert, soll uns im Moment nicht interessieren.)

Der Text-Editor

Für die Erstellung der Quelltextdateien ist ein einfacher Text-Editor größeren Textverarbeitungssystemen stets vorzuziehen. Die meisten Textverarbeitungssysteme verwenden speziellen Formatierungscode, der in dem Dokument mit abgespeichert wird. Dieser zusätzliche Code macht Textverarbeitungssysteme ungeeignet für die Erstellung von Programmquelltexten. Der ASCII-Code (American Standard Code for Information Interchange) definiert ein Standardtextformat, das von fast jedem Programm, einschließlich dem C-Compiler, verstanden wird.

Wenn Sie eine Quelltextdatei abspeichern, müssen Sie ihr einen Namen geben. Der Name sollte darauf verweisen, was das Programm macht. Außerdem sollten die Quelltextdateien Ihres C-Programms die Extension .c erhalten. Sie können zwar Ihren Quelltextdateien beliebige Namen und Extensionen geben, aber .c ist die anerkanntermaßen korrekte Extension.

Für Linux stehen viele Text-Editoren zur Verfügung, unter anderem vi, emacs, joe, ed, vim, crisp und jed. Einige dieser Editoren können von der Konsole aus ausgeführt werden (der schwarzweiße Bildschirm, den Sie sehen, wenn Linux startet und bevor die grafische Benutzerschnittstelle erscheint), andere wiederum bedürfen der grafischen Benutzerschnittstelle X Window. Zu den empfehlenswertesten Editoren mit ausschließlich grafischer Benutzeroberfläche gehören nedit, gnp und kedit. Die Nutzung dieser Text-Editoren sollte allen, die bereits einmal mit einem Textverarbeitungssystem gearbeitet haben, nicht allzu schwer fallen. In Abbildung 1.2 werden diese drei Editoren gemeinsam auf einem Bildschirm angezeigt.

Folgendermaßen können Sie herausfinden, ob einer dieser Editoren auf Ihrem Rechner vorhanden ist: Tippen Sie den jeweiligen Namen gefolgt von dem Ampersand-Zeichen (&) in die Befehlszeile ein. Das & erhalten Sie, indem Sie die Umschalttaste zusammen mit der Taste 6 drücken. Auf diese Weise wird der Editor im Hintergrund ausgeführt und Sie können weiterhin Befehle auf der Konsole eingeben.

Abbildung 1.2:  Text-Editor kedit.

Alternative Text-Editoren für Linux suchen Sie am besten auf einer der vielen Web-Sites im Internet, die Linux-Programme zum Herunterladen auflisten, oder Sie bedienen sich einer Internet-Suchmaschine. Am geschicktesten ist es jedoch, wenn Sie gleich zu der Web-Site der von Ihnen verwendeten Linux-Version gehen.

Quellcode kompilieren

Auch wenn Sie vielleicht in der Lage sind, C-Code zu verstehen (spätestens nach dem Studium dieses Buches werden Sie dazu in der Lage sein) - Ihr Computer versteht den Code nicht. Ein Computer benötigt digitale beziehungsweise binäre Anweisungen in der so genannten Maschinensprache. Bevor Ihr C-Programm auf einem Rechner ausgeführt werden kann, muss der Quellcode in die Maschinensprache übersetzt werden. Diese Übersetzung, der zweite Schritt in der Programmentwicklung, wird von einem so genannten Compiler-Programm erledigt. Der Compiler erhält Ihren Quelltext als Eingabe und erzeugt daraus eine Datei, in der die Anweisungen des Quellcodes in Maschinensprache vorliegen.

Der bekannteste C-Compiler unter Linux ist der GNU-C-Compiler namens gcc.

Um festzustellen, ob der C-Compiler bereits installiert ist, geben Sie den Befehl gcc -v in die Befehlszeile ein. Ist er installiert, erhalten Sie eine Nachricht, die ungefähr der Nachricht auf der Konsole in Abbildung 1.3 entspricht. Und zerbrechen Sie sich nicht den Kopf, wenn Ihre Nachricht nicht mit der abgebildeten Meldung identisch ist. Dann haben Sie wahrscheinlich eine etwas andere C-Compiler-Version. Wenn die Nachricht jedoch besagt, dass der Befehl nicht gefunden wurde, sollten Sie das Handbuch zu Ihrer Linux-Version zu Rate ziehen und herausfinden, wie man den C-Compiler installiert. Dabei ist es ratsam, bei der Installation des C-Compilers die anderen Entwicklungs-Tools gleich mitzuinstallieren.

Abbildung 1.3:  Eine typische Red Hat 6.1 Installation mit einer Konsole, die die Ergebnisse der Befehle gcc -v und make -v zeigt.

Der Compiler gcc wird von der Befehlszeile ausgeführt. Vorausgesetzt die Quelltextdatei radius.c befindet sich im aktuellen Verzeichnis, lautet der Befehl zur Kompilierung und Erzeugung einer ausführbaren Datei:

gcc radius.c

Damit erzeugen Sie in dem aktuellen Verzeichnis eine Ausgabedatei, die traditionell a.out heißt. Um selbst einen Dateinamen für die Ausgabedatei vorzugeben, müssen Sie gcc wie folgt aufrufen:

gcc radius.c -o radius

Dieser Befehl weist gcc an, eine Quelltextdatei namens radius.c zu kompilieren und eine Ausgabedatei namens radius zu erzeugen. Diese Ausgabedatei (die auch einen gänzlich anderen Namen erhalten könnte) ist eine ausführbare Datei, sprich ein Programm, das auf Ihrem Computer ausgeführt werden kann. Um das Programm auszuführen, geben Sie bei dem Befehlszeilen-Prompt den Befehl ./radius ein. Der Punkt und der Schrägstrich signalisieren dem Befehls-Interpreter auf der Konsole, das Programm namens radius im aktuellen Verzeichnis zu suchen. Ohne ./ würde der Befehls-Interpreter in dem so genannten aktuellen Pfad danach suchen (führen Sie den Befehl echo $PATH aus, um sich den aktuellen Pfad anzuschauen).

Der C-Compiler kann jedoch nicht nur Ihren C-Quellcode in eine ausführbare Datei kompilieren, sondern Ihnen auch mitteilen, wo Fehler bei der Kompilierung aufgetreten sind. Dabei wäre es jedoch wenig sinnvoll, wenn der Compiler lediglich die Fehler im Quelltext registrierte, ohne Ihnen anzuzeigen, wo und wieso die Fehler aufgetreten sind. Der C-Compiler kann außerdem Warnungen ausgeben, wenn er auf Code trifft, den er zwar übersetzen kann, der aber vermutlich zu einem Fehler im Programm führt. Verständlicherweise möchten Sie als Programmierer so viele Informationen wie möglich über potentielle Fehler in Ihrem Programm. Deshalb ist es sinnvoll, den Compiler so einzustellen, dass er möglichst viele Warnungen erzeugt. Wenn Sie Ihr Programm darüber hinaus mit dem ddd-Debugger kontrollieren wollen, müssen Sie den Compiler anweisen, zusätzliche, vom Debugger benötigte Informationen in die ausführbare Datei mit aufzunehmen. Der Aufruf von gcc, der alle Warnungen einschaltet und Debug-Informationen hinzufügt, lautet:

gcc -Wall -ggdb radius.c -o radius

Die Direktive -Wall teilt gcc mit, alle möglichen Warnungen auszugeben, während -ggdb dazu dient, die Debug-Informationen für den gdb-Debugger, der von ddd verwendet wird, hinzuzufügen. Auf diese Weise werden Sie die meisten Programme in diesem Buch kompilieren. Am Tag 20, »Compiler für Fortgeschrittene«, werden wir uns dem Thema zuwenden, wie man Programme schreibt und kompiliert, die aus mehreren C-Quelltextdateien bestehen. Aber erst einmal sind unsere Programme alle in einer einzigen Quelltextdatei untergebracht.

Den Entwicklungszyklus abschließen

Nachdem Ihr Programm kompiliert ist und eine ausführbare Datei erzeugt wurde, können Sie es ausführen, indem Sie den Namen auf der Konsole eingeben. Denken Sie jedoch daran, vor den Namen ./ zu setzen. Wenn Sie nach Ausführung des Programms Ergebnisse erzielen, die nicht Ihren Erwartungen entsprechen, müssen Sie zurück zu Schritt 1. Stellen Sie fest, wo der Fehler liegt, und ändern Sie dann den Quelltext entsprechend. Alle Änderungen am Quelltext machen eine erneute Kompilierung des Programms erforderlich, um eine korrigierte Version der ausführbaren Datei zu erhalten. Dieser Zyklus wird so lange durchlaufen, bis Ihr Programm genau das macht, wofür es geschrieben wurde.

Auch als Neuling in der Programmentwicklung werden Sie bald feststellen, dass Programme bei ihrer ersten Ausführung selten das tun, was sie sollen. Zum Auffinden und Beheben von Fehlern in einem Programm gibt es ein spezielles, häufig eingesetztes Programmierwerkzeug, den so genannten Debugger. Ein Debugger ist ein Programm, das es dem Programmierer erlaubt, sein Programm auf der Suche nach potentiellen Fehlern Zeile für Zeile durchzugehen. Abbildung 1.4 zeigt Ihnen den ddd-Debugger, der eine grafische Benutzeroberfläche aufweist. Ich möchte Ihnen nahe legen, dieses Programm das ganze Buch hindurch einzusetzen. Verwenden Sie es nicht nur zum Debuggen, sondern auch zum Lernen. Verwenden Sie es, um Ihre Programme schrittweise durchzugehen und Einsicht in die Funktionsweise Ihrer Programme zu bekommen. Etwas weiter hinten, im Abschnitt »Der ddd-Debugger«, beschreibe ich kurz, wie Sie ddd nutzen können, um ein einfaches Programm zeilenweise zu durchlaufen.

Abbildung 1.4:  Der ddd-Debugger. Er weist zwei Fenster auf: ein Hauptfenster, in dem der Code angezeigt wird, und ein zweites kleineres Fenster mit Steuerschaltflächen (rechts).

Andere Programmierwerkzeuge

Es gibt noch ein weiteres wichtiges Programmierwerkzeug, das vorhanden sein sollte: das make-Programm. Nach der Eingabe von make -v in der Befehlszeile sollte eine Nachricht wie in Abbildung 1.3 erscheinen, auch wenn Sie nicht absolut identisch sein muss. Mit dem make-Programm beschäftigen wir uns erst am Tag 20, wenn wir auf die Kompilierung von Mehrdateienprogrammen zu sprechen kommen.

Das letzte Programm, das Sie noch benötigen, dient dazu, die Programmierer- Dokumentation Ihres Linux-Systems einzusehen. Außer den üblichen Manpages (siehe Abschnitt 1.4) gibt noch eine Unmenge von nützlichen Informationen, die im GNU- Format verfügbar sind. Sie können diese Informationen mit Hilfe des Programms info anzeigen lassen. Geben Sie info im Konsolenfenster ein und Sie erhalten einen einführenden Bildschirm zu dem Informationssystem (drücken Sie q für »quit«, wenn Sie das Programm wieder verlassen wollen). Leider ist das Programm info nicht sonderlich benutzerfreundlich, aber viele Linux-Systeme verfügen über eigene Dokumentations-Leseprogramme wie kdehelp oder gnome-help-browser. Um festzustellen, ob eines dieser Programme auf Ihrem System installiert ist, brauchen Sie nur den Namen auf der Befehlszeile Ihrer Konsole eintippen. Ist eines der Programme verfügbar, versuchen Sie die Informationsseiten »System GNU Info Contents« unter kdehelp und »Info Pages« unter gnome-help-browser zu finden. Zu Ihrer Information: Beide Systeme können auch dazu benutzt werden, die Manpages einzusehen.

Erste Schritte mit Linux

Setzen wir in diesem Buch einfach mal voraus, dass Linux auf Ihrem System bereits läuft und dass Sie schon das Vorhandensein der erforderlichen Werkzeuge überprüft haben. Gehen wir weiter davon aus, dass Sie über die grafische X Window- Benutzerschnittstelle verfügen. Sollte diese Schnittstelle noch fehlen, installieren Sie sie mit Hilfe der Dokumentation zu Ihrer Linux-Version.

Sobald Sie soweit sind, sich in Ihr System einzuloggen, sollten Sie ein Konsolenfenster aufrufen (siehe Abbildung 1.3). Unter der Standardinstallation von Red Hat Linux 6.0/6.1 heißt das Fenster »Terminal«, unter anderen Linux-Distributionen läuft das Konsolenfenster unter der Bezeichnung xterm, kconsole oder Konsole.

Falls Sie derzeit als root-Anwender, das heißt als Systemadministrator, auf Ihrem Linux-System gemeldet sind, sollten Sie ein Benutzerkonto ohne Privilegien einrichten und dieses für Ihr Studium von C verwenden. Das Konto des root-Anwenders hat uneingeschränkten Zugriff auf die Maschine und kann deshalb grenzenlosen Schaden anrichten, wenn ein Programm aus dem Ruder läuft. Als Benutzer ohne Privilegien auf einem korrekt eingerichteten Linux-Rechner können Sie schlimmstenfalls Ihre eigenen Dateien beschädigen. Es ist äußerst unwahrscheinlich, dass Sie Dateien beschädigen, die zum Betriebssystem gehören oder von diesem benötigt werden.

Wenn das Konsolenfenster angezeigt wird, sollten Sie eine Reihe der geläufigsten Befehle ausprobieren, wie zum Beispiel ls (Verzeichnis auflisten), pwd (Arbeitsverzeichnis ausgeben), ps (Prozesse auflisten), mkdir (Verzeichnis anlegen) und cd (Verzeichnis wechseln). Alle Befehle in Linux unterscheiden zwischen Groß- und Kleinschreibung. Der Befehl LS (wenn es ihn gäbe) entspricht nicht dem Befehl ls. Weitere Informationen zu diesen Programmen können Sie den Manpages entnehmen (mit Hilfe des Befehls man). Der Aufruf von man ls zum Beispiel wird Ihnen alles Wissenswerte zu dem Befehl ls liefern. Wenn Sie die Manpage verlassen wollen, drücken Sie die Taste q, um zur Befehlszeile zurückzukehren. Die meisten Linux- Versionen enthalten Manpages zu fast allen Programmen und Betriebssystemeigenschaften.

Die Konsole besteht eigentlich aus zwei Programmen: eines für das Fenster selbst und ein zweites, den so genannten Befehlsinterpreter, der, wie der Name schon verrät, die vom Benutzer eingegebenen Befehle interpretiert und ausführt. Der am weitesten verbreitete Befehlsinterpreter unter Linux heißt GNU bash (Bourne Again SHell), obwohl auch viele andere zur Verfügung stehen.

Der größte Teil der Programme in diesem Buch, die Sie zum Üben der C- Programmierung schreiben, werden von der Befehlszeile einer Konsole ausgeführt.

Ihr erstes C-Programm

Wahrscheinlich warten Sie schon gespannt darauf, Ihr erstes Programm in C zu schreiben. Damit Sie mit Ihrem Compiler schnell vertraut werden, finden Sie in Listing 1.1 ein kurzes Programm, anhand dessen wir den Zyklus der Programmerstellung durchexerzieren werden. Wahrscheinlich werden Sie im Moment noch nicht alles verstehen, aber Sie erhalten zumindest ein Gefühl für den Ablauf des Entwicklungszyklus: Schreiben, Kompilieren und Ausführen eines richtigen C- Programms.

Bei diesem Beispiel handelt es sich um ein Programm namens hallo.c, das nichts anderes macht, als die Worte »Hallo, Welt!« auf dem Bildschirm auszugeben. Dieses Programm, mit dem traditionell in die C-Programmierung eingeführt wird, ist ein gutes Lernbeispiel. Der Quellcode für hallo.c befindet sich in Listing 1.1. Wenn Sie dieses Listing abtippen, müssen Sie die Zeilennummerierung und die Doppelpunkte zur Linken fortlassen.

Listing 1.1: hallo.c.

1:  #include <stdio.h>
2:
3: int main(void)
4: {
5: printf("Hallo, Welt!\n\n");
6: return 0;
7: }

Stellen Sie sicher, dass, wie bereits vorher beschrieben, gcc auf Ihrem Rechner installiert ist und ordnungsgemäß funktioniert und dass Sie über einen geeigneten Text-Editor verfügen. Sind Compiler und Editor bereit, dann folgen Sie den nachstehenden Schritten, um hallo.c einzugeben, zu kompilieren und auszuführen.

hallo.c eingeben und kompilieren

Gehen Sie beim Eingeben und Kompilieren des Programms hallo.c wie folgt vor:

  1. Wechseln Sie im Konsolenfenster mit dem Befehl cd zu dem Verzeichnis, in dem Sie das C-Programm abspeichern wollen, und starten Sie Ihren Text-Editor. Wenn Sie zum Beispiel nedit als Editor verwenden, geben Sie den Befehl nedit & nach dem Befehlsprompt ein.
  2. Geben Sie mit Hilfe der Tastatur den Quellcode von hallo.c genauso ein wie in Listing 1.1. Drücken Sie nach jeder Zeile die Eingabetaste.

Lassen Sie die Zeilennummern und Doppelpunkte fort. Sie dienen lediglich dazu, in diesem Buch den Verweis auf bestimmte Quelltextzeilen zu vereinfachen.

  1. Speichern Sie den Quelltext. Geben Sie der Datei den Namen hallo.c.
  2. Überprüfen Sie, ob hallo.c sich auf Ihrer Festplatte befindet, indem Sie die Liste der Dateien in dem Verzeichnis mit dem Befehl ls im Konsolenfenster anzeigen lassen. Unter den angezeigten Dateien sollte auch hallo.c zu finden sein.
  3. Kompilieren Sie hallo.c mit dem folgenden Befehl im Konsolenfenster zu einem richtigen Programm.
    gcc -Wall -ggdb hallo.c -o hallo
  4. Prüfen Sie die Compiler-Meldungen. Wenn Sie keine Fehlermeldungen oder Warnungen erhalten, sollte alles soweit in Ordnung sein.
  5. Wenn Ihnen beim Abtippen des Programms ein Fehler unterlaufen ist, wird der Compiler diesen Fehler abfangen und eine Fehlermeldung ausgeben. Wenn Sie zum Beispiel statt printf das Wort prntf eingegeben hätten, würden Sie ungefähr folgende Meldung erhalten:
    hallo.c: In function `main':
    hallo.c:5: warning: implicit declaration of function `prntf'
    /tmp/cco48R7q.o: In function `main':
    /home/erikd/hello/hallo.c:5: undefined reference to `prntf'
    collect2: ld returned 1 exit status
  6. Wenn Sie eine solche oder eine ähnliche Fehlermeldung erhalten, sollten Sie zu Schritt 2 zurückkehren. Öffnen Sie die Datei hallo.c in Ihrem Editor. Vergleichen Sie den Inhalt Ihrer Datei noch einmal sorgfältig mit Listing 1.1. Nehmen Sie alle notwendigen Korrekturen vor und fahren Sie dann mit Schritt 3 fort.
  7. Ihr erstes C-Programm sollte nun kompiliert und ausführbar sein. Wenn Sie jetzt aus dem Verzeichnis alle Dateien mit dem Namen hallo (und einer beliebigen Extension) auflisten, sollten Sie folgendes Ergebnis erhalten:
  8. hallo.c - die Quelltext-Datei, die Sie mit Ihrem Editor erstellt haben
  9. hallo - das beim Kompilieren und Linken von hallo.c erzeugte ausführbare Programm
  10. Um hallo auszuführen, müssen Sie lediglich ./hallo eingeben. Damit wird die Meldung »Hallo, Welt!« auf dem Bildschirm ausgegeben.

Meinen Glückwunsch! Sie haben gerade Ihr erstes C-Programm eingegeben, kompiliert und ausgeführt. Zugegeben, hallo.c ist ein einfaches Programm, das eigentlich nichts besonders Nützliches macht, aber es ist immerhin ein Anfang. Und um ehrlich zu sein, die meisten der heutigen C-Experten haben C auf genau dem gleichen Weg gelernt - durch das Kompilieren von hallo.c. Sie befinden sich also in bester Gesellschaft.

Kompilierfehler

Ein Kompilierfehler tritt auf, wenn der Compiler irgendetwas im Quellcode findet, das er nicht kompilieren kann. Fehlerhafte Schreibweise, typografische Fehler oder ein Dutzend anderer Dinge können beim Compiler einen Fehler auslösen. Zum Glück jedoch brechen moderne Compiler den Kompiliervorgang nicht ab, ohne Ihnen mitzuteilen, warum sie versagt haben und wo das Problem liegt. Damit haben Sie es wesentlich leichter, Fehler in Ihrem Quelltext aufzuspüren und zu korrigieren.

Um Ihnen dies einmal zu veranschaulichen, wurde in dem Programm hallo.c von oben absichtlich ein Fehler eingefügt. Wenn Sie das Beispiel durchgearbeitet haben (und das sollten Sie), haben Sie inzwischen eine Kopie von hallo.c auf Ihrer Festplatte. Rufen Sie Ihren Editor auf und setzen Sie den Cursor an das Ende der Zeile mit dem Aufruf von printf(). Entfernen Sie dort das abschließende Semikolon. Danach sollte hallo.c wie in Listing 1.2 aussehen.

Listing 1.2: hallo.c mit einem Fehler.

1:  #include <stdio.h>
2:
3: int main(void)
4: {
5: printf("Hallo, Welt!\n\n")
6: return 0;
7: }

Sichern Sie danach die Datei. Jetzt können Sie sie erneut kompilieren. Geben Sie dazu den entsprechenden Befehl an den Compiler ein. Wegen des Fehlers wird die Kompilierung nicht abgeschlossen. Statt dessen zeigt Ihnen der Compiler in etwa folgende Meldung an:

hallo.c: In function `main':
hallo.c:6: parse error before `return'
hallo.c:7: warning: control reaches end of non-void function

Der kleine, von Ihnen eingebaute Fehler hat drei Compiler-Meldungen ausgelöst. Jede Meldung gibt am Zeilenanfang den Namen der C-Quelltextdatei an, die zweite und dritte Meldung schließt daran sogar noch die Nummer der Zeile an, in der der Fehler festgestellt wurde. Beachten Sie, dass es sich bei der dritten Meldung um eine Warnung handelt.

Die Meldungen sind recht informativ. Sie teilen Ihnen mit, dass in der Funktion `main' etwas falsch gelaufen und in Zeile 6 vor `return' ein Fehler aufgetreten ist. Warum, werden Sie sich fragen, stellt der Compiler einen Fehler in Zeile 6 fest, wo wir doch das Semikolon vom Ende der Zeile 5 entfernt haben? Die Antwort lautet, dass C so etwas wie Zeilenumbrüche nicht registriert. Das Semikolon, das hinter die printf()- Anweisung gehört, hätte genauso gut auch in die nächste Zeile gesetzt werden können (auch wenn dies nicht unbedingt der gängigen Programmierpraxis entspricht). Erst wenn der Compiler auf den nächsten Befehl (return) in Zeile 6 trifft, weiß er, dass das Semikolon fehlt. Deshalb befindet sich für den Compiler der Fehler in Zeile 6.

Außerdem sollten Sie sich merken, dass ein Fehler in einem Teil des Programms (Zeile 6) manchmal weiter hinten im Programm (Zeile 7) einen weiteren Fehler bewirken kann. Daraus können Sie Folgendes lernen: Wenn der Compiler mehrere Fehler auflistet und Sie nur einen finden können, sollten Sie diesen Fehler erst einmal beheben und das Programm dann erneut kompilieren. Vielleicht haben Sie damit bereits alle anderen Fehler mitbeseitigt und können das Programm ohne weitere Fehlermeldungen kompilieren.

Damit dürfte ein Punkt bezüglich des C-Compilers und seiner Fehlermeldungen absolut klar geworden sein. Ein Compiler mag zwar so intelligent sein, Fehler festzustellen und zu lokalisieren, aber er ist kein Einstein. Mit Ihrem Wissen der Programmiersprache C müssen Sie die Fehlermeldungen des Compilers interpretieren und die eigentliche Position der angemerkten Fehler feststellen. Meistens befinden sich die Fehler in der von dem Compiler angegebenen Zeile und wenn nicht, sind sie fast immer in der vorangehenden Zeile zu finden. Sie werden am Anfang sicher etwas Probleme haben, die Fehler aufzuspüren, aber das wird sich schon bald legen.

Der ddd-Debugger

In dem Abschnitt zum C-Entwicklungszyklus bestand der vierte Schritt darin, das Programm auszuführen, um festzustellen, ob es korrekt läuft. Es ist ohne weiteres möglich, ein C-Programm zu schreiben, das sich problemlos kompilieren lässt, aber dennoch nicht den Zielvorstellungen entspricht. In diesem Fall sprechen wir von einem logischen Fehler im Vergleich zu den Kompilierfehlern, die wir im vorangehenden Abschnitt besprochen haben. Logische Fehler in großen Programmen aufzuspüren, ist wesentlich schwieriger als Kompilierfehler festzustellen. Hier ist uns der Debugger eine wertvolle Hilfe, denn er ermöglicht es uns, ein Programm zeilenweise durchzugehen. Auf diese Art und Weise können Sie den Programmablauf Zeile für Zeile verfolgen und prüfen, ob das Programm auch so arbeitet, wie Sie es beim Schreiben des Programms beabsichtigt hatten. In diesem Buch werden wir den ddd-Debugger weniger zum Debuggen, sondern vielmehr als Lernhilfe verwenden.

Bevor Sie den ddd-Debugger einsetzen können, müssen Sie ihn erst einmal korrekt einrichten. Angenommen Sie haben ddd bereits zur Verfügung, dann starten Sie ihn vom Konsolenfenster mit der Eingabe von ddd. Wenn Sie ddd zum ersten Mal nutzen, müssen Sie sich durch ein oder zwei Start-Bildschirme durchklicken, bis Sie zum Hauptfenster kommen. Klicken Sie dann in der Menüleiste auf Edit (Bearbeiten) und wählen Sie aus dem zugehörigen Menü den Punkt GDB Settings (GDB-Einstellungen) aus. Sie gelangen dann in ein Dialogfeld mit einer Bildlaufleiste zur Rechten. Scrollen Sie mit dieser Bildlaufleiste bis ungefähr zur Mitte, bis Sie zu dem Punkt Autoloading of Shared Library Symbols (Gemeinsame Bibliothekssymbole automatisch laden) kommen. Entfernen Sie dann, wie in Abbildung 1.5 zu sehen, durch Klicken die Markierung aus dem Kästchen links von diesem Punkt, so dass die Option ausgeschaltet ist. Um Ihre Änderungen zu sichern, müssen Sie im Dialogfeld den OK- Schalter anklicken und dann im Menü Edit (Bearbeiten) auf Save Options (Optionen sichern) klicken.

Jetzt können Sie damit beginnen, mit ddd ein Programm zu debuggen. Setzen Sie in Ihrem Editor den Quelltext zu dem nachfolgenden Programm auf (Listing 1.3) und kompilieren Sie es. Denken Sie daran, gcc mitzuteilen, die Debug-Informationen, die vom Debugger benötigt werden, hinzuzufügen. Das ausführbare Programm sollte den Namen hallo2 erhalten.

Listing 1.3: hallo2.c, ein Programm zum Experimentieren mit dem Debugger.

1 : #include <stdio.h>
2 :
3 : int main(void)
4 : { int count ;
5 :
6 : printf ("Hallo!!!\n") ;
7 :
8 : printf ("Start ... \n") ;
9 : for (count = 0 ; count < 5 ; count++)
10: printf ("Zaehler = %d\n", count) ;
11:
12: printf ("fertig.\n\n") ;
13:
14: return 0 ;
15: }

Abbildung 1.5:  Den ddd-Debugger einrichten.

Nachdem das Programm ordnungsgemäß kompiliert und ausgeführt wurde, können Sie den Debugger einsetzen. Um den Debugger für dieses Programm aufzurufen, geben Sie nach dem Befehlsprompt des Konsolenfensters

ddd hallo2

ein. Daraufhin sollten Sie die zwei Fenster des ddd-Debuggers und ein Dialogfeld mit Tipps zur Arbeit mit ddd erscheinen (das Dialogfeld können Sie gleich schließen). Das Hauptfenster sollte den Quelltext zu hallo2.c enthalten.

Der erste Schritt bei der Arbeit mit ddd besteht darin, einen ersten Haltepunkt zu setzen, an dem der Debugger nach der Initialisierung anhalten soll. Klicken Sie dazu im Hauptfenster ganz links neben die erste Zeile, die eine »printf«-Anweisung (Zeile 6) enthält, und anschließend in der Symbolleiste auf den »break«-Schalter (Schalter mit dem Stoppzeichen darüber). In der Zeile mit dem printf-Befehl sollte daraufhin ein Stoppzeichen angezeigt werden. Jetzt können Sie den Schalter Run (Ausführen) auf der frei beweglichen Schalterleiste anklicken, woraufhin ein grüner Pfeil neben dem Stoppzeichen erscheint. Wenn Sie jetzt in der Schalterleiste auf den Schalter Step (Schritt) klicken, können Sie den Code zeilenweise durchgehen. Die Ausgabe, die von jeder Codezeile erzeugt wird, erscheint im unteren Teil des Hauptfensters. Es leuchtet ein, dass der Debugger nicht über das Ende des Programms hinaus gehen kann, aber Sie können jederzeit den Debugger das Programm von vorne durchgehen lassen, indem Sie auf den Run-Schalter klicken.

Scheuen Sie sich nicht, mit dem Debugger die Beispielprogramme in diesem Buch durchzugehen. Die Arbeit mit dem Debugger wird Ihnen einen viel besseren Einblick in das Zusammenspiel zwischen der Programmiersprache C und der Arbeitsweise Ihres Rechners geben.

Zusammenfassung

Nachdem Sie diese Lektion gelesen haben, sollten Sie davon überzeugt sein, dass Sie mit C als Programmiersprache für Linux eine weise Entscheidung getroffen haben. C kombiniert auf unübertroffene Weise Power, Popularität und Portabilität. Diese Faktoren, zusammen mit der engen Verwandtschaft zu objektorientierten Sprachen wie C++ oder Java, machen C fast unschlagbar.

In dieser Lektion haben Sie die verschiedenen Schritte bei der Erstellung eines C- Programms kennen gelernt - einen Prozess, den man auch Programmentwicklung nennt. Ihnen sollten jetzt sowohl der Zyklus Bearbeiten-Kompilieren-Testen als auch die für jeden Schritt erforderlichen Werkzeuge vertraut sein.

Fehler sind unvermeidbarer Bestandteil der Programmentwicklung. Ihr C-Compiler kann diese Fehler in Ihrem Quelltext aufspüren und eine entsprechende Fehlermeldung ausgeben, die Ihnen mitteilt, welcher Art der Fehler und wo er zu finden ist. Mit diesen Informationen können Sie Ihren Quelltext erneut bearbeiten und den Fehler beheben. Denken Sie jedoch daran, dass der Compiler nicht immer mit 100-prozentiger Sicherheit die Art und Position des Fehlers feststellen kann. Manchmal müssen Sie Ihre Kenntnisse in C zur Hilfe nehmen, um herauszufinden, was genau eine Fehlermeldung ausgelöst hat.

Fragen und Antworten

Frage:
Wenn ich zur Eingabe meines Quellcodes einen Text-Editor verwendet habe, der mir eigentlich nicht gefällt, kann ich dann zu einem anderen wechseln, ohne den bisher aufgesetzten Code erneut einzugeben? Sind alle Text-Editoren miteinander kompatibel?

Antwort:
Ja, alle Text-Editoren sind kompatibel. Wenn Sie einen Text-Editor und kein Textverarbeitungsprogramm verwenden, enthalten die von Ihnen erzeugten Dateien nur ASCII-Zeichen. Der Wechsel zu einem anderen Text-Editor sollte also keine Schwierigkeit darstellen, auch wenn einige Editoren unter Umständen das [ÿ]-Zeichen etwas anders darstellen und es mit vier Leerzeichen gleichsetzen anstatt wie normalerweise mit acht.

Frage:
Wenn ich ein von mir geschriebenes Programm jemand anderem zur Verfügung stellen will, welche Dateien muss ich ihm dann mitgeben?

Antwort:
Einer der Vorteile von C ist, dass es sich um eine kompilierte Sprache handelt. Das bedeutet, dass Sie nach der Kompilierung des Quellcodes ein ausführbares Programm erhalten. Dieses ausführbare Programm ist unabhängig. Wenn Sie also all Ihren Freunden, die unter Linux arbeiten, hallo geben wollen, steht dem nichts im Wege. Sie müssen Ihnen nur das ausführbare Programm hallo mitgeben.

Wenn Sie jedoch dieser Person die Möglichkeit zugestehen wollen, das Programm seinen eigenen Bedürfnissen oder seinem Rechner anzupassen, müssen Sie ihm den C-Quellcode zur Verfügung stellen. Dieser Quellcode muss dann jedoch erst kompiliert werden, bevor er auf dem neuen Rechner läuft. Geben Sie, wenn nötig, auch Anweisungen mit, wie Ihr Programm zu kompilieren ist.

Frage:
Muss ich die Quelltextdatei (.c) behalten, nachdem ich eine ausführbare Datei erstellt habe?

Antwort:
Wenn Sie die Quelltextdatei löschen, nehmen Sie sich die Möglichkeit, Änderungen an dem Programm vorzunehmen. Deshalb sollten Sie diese Datei behalten. Solange Sie über die Quelltextdatei (.c) verfügen, können Sie jederzeit die anderen Dateien neu erstellen.

Frage:
Kann ich die Fehlermeldungen ignorieren?

Antwort:
Einige Warnungen beeinflussen die Ausführung des Programms und andere nicht. Wenn der Compiler eine Warnung ausgibt, sollte dies für Sie ein Signal sein, dass irgendetwas nicht in Ordnung ist. Sie sollten jede Warnung analysieren und eine Entscheidung fällen. Am besten ist es, wenn Sie Ihre Programme so schreiben, dass sie absolut keine Warnungen oder Fehler enthalten. (Wenn ein Fehler auftritt, erzeugt der Compiler keine ausführbare Datei.)

Workshop

Der Workshop enthält Quizfragen, die Ihnen helfen sollen, Ihr Wissen zu festigen, sowie Übungen, die Sie anregen sollen, das Gelernte umzusetzen und eigene Erfahrungen zu sammeln. Die Lösungen zu den Fragen und den Übungen finden Sie in Anhang C.

Quiz

  1. Nennen Sie drei Gründe, warum C als Programmiersprache die beste Wahl ist.
  2. Was macht der Compiler?
  3. Aus welchen Schritten besteht der Programmentwicklungszyklus?
  4. Welchen Befehl müssen Sie eingeben, um mit gcc ein Programm namens meinprog aus einer C-Quelltextdatei namens programm1.c zu erstellen?
  5. Welche Extension sollten Sie für Ihre C-Quelltextdateien verwenden?
  6. Ist dateiname.txt ein gültiger Name für eine C-Quelltextdatei?
  7. Was ist zu tun, wenn ein kompiliertes und ausgeführtes Programm sich nicht wie erwartet verhält?
  8. Was versteht man unter der Maschinensprache?
  9. Was macht der Debugger?
  10. Welche Informationen werden vom Debugger benötigt und vom Compiler bereitgestellt?

Übungen

  1. Verwenden Sie Ihren Text-Editor, um die ausführbare Datei, die Sie aus dem Listing 1.1 erzeugt haben, anzuschauen. Sieht die ausführbare Datei aus wie die Quelltextdatei? (Speichern Sie diese Datei nicht, wenn Sie den Editor verlassen.)
  2. Geben Sie das folgende Programm ein und kompilieren Sie es. Was macht das Programm? (Lassen Sie die Zeilennummern und die Doppelpunkte am Zeilenanfang weg.)
    1:  #include <stdio.h>
    2:
    3: int radius, flaeche;
    4:
    5: int main(void)
    6: {
    7: printf( "Geben Sie einen Radius ein (z.B. 10): " );
    8: scanf( "%d", &radius );
    9: flaeche = (int) (3.14159 * radius * radius);
    10: printf( "\n\nFläche = %d\n", flaeche );
    11: return 0;
    12: }
  3. Geben Sie das folgende Programm ein und kompilieren Sie es. Was macht das Programm?
    1:  #include <stdio.h>
    2:
    3: int x,y;
    4:
    5: int main(void)
    6: {
    7: for ( x = 0; x < 10; x++, printf( "\n" ) )
    8: for ( y = 0; y < 10; y++ )
    9: printf( "X" );
    10:
    11: return 0;
    12: }
  4. FEHLERSUCHE: Das folgende Programm weist ein Problem auf. Geben Sie es in Ihren Editor ein und kompilieren Sie es. Welche Zeilen erzeugen Fehlermeldungen?
    1:  #include <stdio.h>
    2:
    3: int main(void);
    4: {
    5: printf( "Weitersuchen!" );
    6: printf( "Du wirst\'s finden!\n" );
    7: return 0;
    8: }
  5. FEHLERSUCHE: Das folgende Programm weist ein Problem auf. Geben Sie es in Ihren Editor ein und kompilieren Sie es. Welche Zeilen erzeugen Fehlermeldungen?
    1:  #include <stdio.h>
    2:
    3: int main(void)
    4: {
    5: printf( "Dies ist ein Programm mit einem " );
    6: tue_es( "Problem!");
    7: return 0;
    8: }
  6. Nehmen Sie folgende Änderung an dem Programm in Übung 3 vor. Kompilieren und führen Sie das Programm erneut aus. Was macht das Programm jetzt?
    9:  printf( "%c", 1 );


vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbackKapitelanfangnächstes Kapitel


© Markt&Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH