Kurzanleitung für GNU C-/C++-Compiler

Dies ist eine kurze Einleitung in die Bedienung der GNU C++ Compiler. Es ist keine Einführung in die Sprache C. Hierfür verweise ich auf die unten genannte Literatur. Besprochen wird die Compilerung von C++ Programmen für den Terminalmodus von Linux. Die graphische Programmierung von X-Windows mittels der Qt3-/Qt4-Grafikbibliothek finden Sie in den KDE bzw. Qt-Büchern im Anhang.

Die Sprache C bzw. C++ sind die Standardsprachen unter Linux, obwohl praktisch jede heutige Computersprache unter Linux verfügbar ist. UNIX und C sind eng verbunden. Die Sprache C wurde von Kerningham und Ritchie im Jahre 1972 speziell zur Entwicklung von UNIX erfunden. Sie hat sich seit dieser Zeit in mehreren Stufen fortentwickelt. Der alte Kerningham-/Ritchie-Standard wird heute praktisch nicht mehr benutzt, da er zu sehr unleserlichen Programme führen kann. Wer heute in C programmiert, sollte sich an der ANSI-C Standard halten.

Die Sprache C++ wurde von Bjaarne Stroustrup in Jahre 1985 entwickelt. Auch sie hat mehrere Evolutionsstufen bis heute hinter sich. Heute gilt die ANSI C++ 3.0-Version als neuester Standard. C++ erweitert die Sprache C, um die Konzepte der objektorientierten Programmierung. Dies sind die Bildung von Klassen (Datenkapselung), Vererbung, Polymorphismus, die Überladung von Operatoren uvm. Jeder C++-Compiler kann allerdings auch als C-Compiler arbeiten, womit eine Migration von C nach C++ möglich ist.

Linux selbst ist allerdings nicht in C++ geschrieben, sondern in C mit kleineren Assembleranteilen. C eignet sich hervorragend zur Entwicklung von Betriebssystemen, da es hochoptimierten Code erzeugen kann ohne unbedingt auf Assembler ausweichen zu müssen. Der C-Code ist sehr portabel, sodaß Linux heute praktisch auf jedem CPU-Typ verfügbar ist. Die Sprache C++ findet z.B. bei der Qt-Grafikbibliothek ihre Anwendung.


Der Compiler gcc 4.2.1

Alle neuen Linux-Distributionen verwenden beim Aufruf des g++-Befehls bereits den gcc 4.2.1-Compiler. Man beachte, daß der Linux-Kernel als Miminalbasis den für gcc 3.2.0 verwendet.

Mit dem Befehl g++ -v bekommt man heraus, welcher C++-Compiler zum Einsatz kommt.

Der gcc 4.2.1 erzeugt wesentlich besseren Code als die älteren C-Compiler, allerdings ist er dafür um einiges langsamer als der gcc 2.95 beim Compilieren. Dafür erfüllt er die C++ Standards wesentlich besser als die alten Compiler.

Der C++-Compiler (g++) ist ab SuSE 7.x Professionell bereits vorinstalliert.


Kleines C++ Programm zur Übung

C bzw. C++ Programme werden zuerst mit einem Texteditor erstellt. Ich selbst verwende den fortgeschrittenen Editor kwrite seit KDE-Version 1.1. Dieser Editor kann C++ Quelltext farbig hervorheben (Syntax-Highlightning). Um dieses Features zu aktivieren sollte man einen neuen Quelltext möglichst nach der ersten Programmzeile als C++-Datei abspeichern. C++ Programme haben üblicherweise die Dateiendung cpp. Nennen wir unser kleines Programm einfach versuch.cpp

Andere Programmierer schwören auf emacs bzw. Xemacs als Editor, aber für Anfänger ist dies nicht gerade die ideale Mischung. Kwrite ist wirklich einfacher zu handhaben.

Mein kleines C++-Programm tut nicht viel. Es fragt den Benutzer nach seinem Vornamen und begrüßt ihn dann mit Hallo.


#include <iostream>
using namespace std;

void main( void )
{
  char name[50 ];
   cout << "Wie ist Dein Name ?: " ;
   cin >> name;
   cout << "Hallo, " << name << endl;
}


Erklären will ich das Programm hier nicht explizit. C bzw. C++ können Sie in unser LINUX-Gruppe erlernen. Geben Sie einfach den Quelltext ein und speichern Sie ihn unter versuch.cpp ab.


Quelltext compilieren

Aus dem Quelltext kann nun ein Maschinencode-Programm erzeugt werden. Dies tut dankenswerterweise der C++-Compiler für uns. CPU's verstehen nur Maschinencode, nichts anderes. Der C++ Quelltext, obwohl auch nicht immer trivial, ist nur für uns Menschen da.

Der C++-Compiler muß reichlich arbeiten, um unseren menschlichen Quelltext in Maschinensprache zu codieren. Dies sind intern mehrere Stufen, wie lexikalische Analyse, semantische Analyse, Codegenerierung und Codeoptimierung. Der Compiler ruft danach standardmäßig seinen integrierten Linker auf, um die verschiedenen Programmmodule und Programmbibliotheken zu einem startfähigen Programm zusammenzubinden. Compilerbau gehört immer noch zu den höchsten Weihen in der Softwareentwicklung.

1. Übersetzungsversuch

Geben Sie den Befehl: g++   versuch.cpp ein

Der C++-Compiler erzeugt nun ein startfähiges Programm namens a.out.

Das Programm a.out wird immer erzeugt, wenn man keinen eigenen Programmnamen mit angibt.

Starten Sie a.out mit den Befehl:   . /a.out

2. Übersetzungsversuch

Geben Sie den Befehl: g++   versuch.cpp -o versuch ein

Der C++-Compiler erzeugt nun ein startfähiges Programm namens versuch.

Die Compileroption -o weist den Compiler an, die startfähige Datei versuch zu nennen.

Starten Sie versuch mit dem Befehl:   . /versuch



make

Mit Obigem können Sie einfache Programme problemlos übersetzen. Profis müssen allerdings oft komplexe Programme aus mehreren C++-Dateien erzeugen. Dazu benutzt man dann sogenannte Makefiles. In Makefiles werden die Abhängigkeiten der verschiedenen Quelldateien beschrieben.

Hier ein Makefile, welches wir zur Übersetzung unseres Baum-Projekts unter X-Windows (Qt) benutzen.

Der Programmquelltext besteht aus mehreren C++- und Header-Dateien . Das Qt-Programm baum wird mittels eines Makefile übersetzt. Dieses Makefile erstellten wir mit einem Editor. Beachten Sie, daß vor den beiden g++-Befehlszeilen ein Tabulator gesetzt ist (make spezifisch). Die make-Datei heißt makefile. Die Programmübersetzung wird mit dem Befehl make eingeleitet.

INCDIR = -I$(QTDIR)/include
LIBDIR = -L$(QTDIR)/lib
LIBS = -lqt

OBJ = baum.o baum1.o baum2.o equal.o bank.o

#Compilerflags mit Optimierung
#FLAGS = -Wall -pipe -O2 -fno-strength-reduce -DCPU=586 $(INCDIR)
#Compilerflags mit Debugmode ohne Optimierung
FLAGS = -g -Wall $(INCDIR)

all: baum

baum.o: global struct.h
baum1.o: extern.h struct.h
baum2.o: extern.h struct.h
equal.o: extern.h struct.h
bank.o: extern.h struct.h

%o: %cpp
     g++ -c $(FLAGS) -o $@ $<

baum: $(OBJ)
     g++ -o baum $(OBJ) $(LIBDIR) $(LIBS)

Wir sind gerne bereit, Sie in die Geheimnisse von make einzuweisen. Make brauchen Sie nur, wenn Sie größere C-Projekte erstellen wollen.



Einsatz von Debuggern

Größere Programme sind selten fehlerfrei. Um den Fehlern nachzuspüren, setzen Profis sogenannte Debugger ein. Dies sind Programme, mit denen man Programme schrittweise testen kann. Dabei kann man im Quelltext Haltepunkte markieren, um dort Variable und Speicherbereiche zu analysieren.

Unter Linux ist der gdb (GNU-Debugger) im Einsatz. Er ist sehr leistungsstark, aber leider rein textorientiert und kryptisch. Damit ein Normalsterblicher nicht an gdb verzweifelt, werden sogenannte grafische gdb-Frontends eingesetzt, die gdb-Befehle sehr schön aufbereiten.

Das Nonplusultra unter den Linux-Debuggern ist der DDD 3.3.8 (Data Display Debugger) . Der DDD wird noch separat als HTML-Dokument beschrieben werden. Er ist im SuSE-Linux verfügbar (Serie xdev). Für kleinere Projekte ist der KDE-Debugger kdbg 2.0.5 wesentlich leichter zu benutzen. Mit diesem sollte man beginnen.

Debugfähigen Code erzeugen

Von Haus aus enthält ein Maschinenprogramm keinen debugfähigen Code. Es sei denn, man liebt unkommentierten Maschinencode. Um C++-Programme zu debuggen, muß der C++-Compiler eine Symboltabelle mit Variablen und Zeileninformationen an den Code anhängen.

Mit der Compileroption -g weisen wir den GNU-Compiler an, diese Symboltabelle an den Code anzuhängen.

Geben Sie den Befehl: g++   -g versuch.cpp -o versuch ein

Nun 'mag' Ihr Debugger diesen Code und sie können nach Herzenslust Fehler jagen !

Compileroptionen

Die GNU C++-Compiler kennen eine riesige Menge an Compileroptionen, da könnte man ein ganzes Buch verfassen. Ich möchte nur einige wenige nennen :

-c Quelltexte übersetzen, aber nicht linken (bei make)

-DCPU=586 weist den Compiler, an Pentium-CPU-Code zu generieren

-fno-strength-reduce keine Schleifenoptimierungen zulassen

-g Symboltabelle für Debugger an Code anfügen

-I Pfad für die Headerdateien (include)

-L Pfad für die Programmbibliotheken

-l bindet zusätzliche Programm-Bibliotheken (Libraries) ein

-o der nachfolgende Name soll als Programmname verwendet werden

-O2 weist den Compiler an, den Code weiter zu optimieren

-pg Informationen für gprof (Profiler) erzeugen

-pipe Linux-Pipes zum Datenaustausch zwischen Compilerstufen verwenden

-Wall weist den Compiler an, alle auftretenden Warnungen anzeigen

-S weist den Compiler an, den erzeugten Code als Assembler-Quelltext auszugeben

-v gibt die Compiler-Version aus.



Literatur-Verweise

Graphische Programmierung unter Linux:

C++ GUI-Programming with Qt3
Jasmin Blanchette (englisch)
Prentice-Hall 2004
ISBN 0-13124072-2
(sehr aktuell mit Qt 3.2)

Das Qt-Buch
Helmut Herold
SuSE Press 2001
ISBN 3-934678-76-9

KDE2 - Programmierung
David Sweet
Markt+Technik Verlag 2001
ISBN 3-8272-5980-0

KDE- und Qt-Programmierung
2.Auflage
Burckhard Lehner
Addison-Wesley-Verlag 2001
ISBN 3-8273-1477-1

Programming with Qt 2.Auflage
Kalle Dalheimer
O'Reilly-Verlag 2001
ISBN 3-89721-130-0

KDE Programmierung:
Uwe Thiem
Franzis-Verlag
ISBN 3-7723-6124-2

C/C++ Programmierung:

C-Programmierung unter Linux
Helmut Herold
SuSE Press 2002
ISBN 3-935922-08-6

Jetzt lerne ich C++
Jesse Liberty
Markt+Technik Verlag 1999
(sehr schönes Einsteiger-Buch)

C/C++
New Reference
Dirk Louis
Markt & Technik Verlag
ISBN 3-8272-6121-X
(Nachschlagewerk C/C++-Syntax)