ich war hier: ProzProg8GetrennteUebersetzung
 (image: http://wdb.fh-sm.de/uploads/QualipaktLehre/BMBF_Logo_klein.jpg)

Prozedurale Programmierung - Kapitel 8 - Getrennte Übersetzung


Inhalte von Dr. E. Nadobnyh


Der Quellcode eines Programms befindet sich oft in vielen Dateien.

Die Zerlegung in mehrere Dateien hat den selben Zweck wie die Zerlegung in mehrere Funktionen, z.B.:

1) Reduzierung der Komplexität eines Problems,
2) unabhängige Programmierung von Teilen,
3) Wiederverwendung des Codes,
4) Lesbarkeit des Codes,
5) Verbergen der Details von Anwendern.

Es gibt verschiedene Möglichkeiten mehrere Dateien zu einem Programm zusammenzufassen:

1) Präprozessor kann die Quellcode-Dateien binden;
2) Linker kann die übersetzten Dateien binden.


Übersetzungseinheit


Bei der Verarbeitung eines C/C++-Programms werden zunächst die Präprozessoranweisungen übersetzt, z.B. #include-Anweisungen. Das Ergebnis ist dann eine so genannte Übersetzungseinheit (translation unit, Modul).

Ein Compiler übersetzt jede Übersetzungseinheit, die zu einem Programm gehört, unabhängig von allen anderen. Dies wird als die getrennte Übersetzung (separate Compilierung) bezeichnet.

Aus jeder Übersetzungseinheit erzeugt der Compiler eine so genannte Object-Datei.

Aus mehreren Object-Dateien erzeugt der Linker das ausführbare Programm.

Informationen über die Modulen sind in einer Projektdatei zusammengestellt.


Gültigkeitsbereiche


Mit den Übersetzungseinheiten wird ein globaler Gültigkeitsbereich des Programms auf kleinere Bereiche ufgeteilt.

Ein Gültigkeitsbereich (scope, Verfügbarkeitsbereich, Geltungsbereich) ist ein Bereich, in dem auf einen Namen (z.B. Funktion, Variable, Feld) zugegriffen werden kann.

In C werden 4 Bereiche unterschieden :
1) Block,
2) Funktion,
3) Übersetzungseinheit (Modul, Datei),
4) gesamtes Programm (globaler Gültigkeitsbereich).

C++ hat weitere Bereich-Arten. Ein wichtiger Gültigkeitsbereich ist eine Klasse.


Sichtbarkeit


Gültigkeitsbereiche bestimmen eine Sichtbarkeit (Gültigkeit) einer Variable oder Funktion. Es wird zwischen lokaler, modulglobaler und programmglobaler Sichtbarkeit unterschieden.

1) Variablen und Felder sind lokal, wenn sie in einem Block oder in einer Funktion definiert werden.

2) Variablen, Felder und Funktionen sind modulglobal, wenn sie in einem Modul (in einer Übersetzungseinheit) und außerhalb jeder Funktion definiert werden.

3) Variablen, Felder und Funktionen sind programmglobal, wenn sie in einem Modul definiert werden und in anderen Modulen deklariert werden.

Programmglobale Namen werden durch den Linker unterstützt.


Definition und Deklaration


1. Mittels eines Namens können Variablen, Feldnamen, Funktionen, Datentypen und Objekte bezeichnet werden. In C/C++ müssen Namen vor der Verwendung definiert werden.

Eine Definition führt einen Namen ein und legt den Speicherplatz für die Daten oder den Code an. In einem Programm kann nur eine einzige Definition für einen Namen gegeben werden.

2. Soll ein Name vor seiner Definition verwendet werden, muss er zumindest deklariert sein.

Eine Deklaration führt einen Namen ein und gibt dem Namen eine Bedeutung. In einem Programm können mehrere Deklarationen für einen Namen gleichzeitig existieren.


extern


Das Schlüsselwort extern wird bei den Deklarationen verwendet.

1) Variablendeklaration:

Syntax: extern typ name;

Beispiel: extern int a;
extern int b[5];

Besonderheit: Globale Variablen haben automatisch die Speicherklasse extern. Deswegen können sie mit extern auch definiert werden.

Beispiel: extern int a=5;

2) Funktionsdeklaration (Prototyp):

Syntax: extern resulttype name (Parameterliste);
resulttype name (Parameterliste);

Beispiel: extern int sum(int n);
int sum(int n);


Beispiel

 (image: http://ife.erdaxo.de/uploads/ProzProg8GetrennteUebersetzung/pp53.gif)


Legende:
Diese Verbindungen werden durch den Linker hergestellt.

⇒ Demo 1.


Überblick


Die folgende Tabelle stellt Definitionen und Deklarationen syntaktisch gegenüber:

Funktion Variable
Definition void f1(int x){...} int a = 3;
Deklaration void f1(int x); //Prototyp extern int a;
Verwendung f1(4); //Aufruf a=5; //Zugriff



8.2. Header-Dateien
1)Deklarationen von Funktionen, Variablen, Feldern müssen in allen Modulen gleich lauten.

2)Deklarationen müssen mit den Definitionen übereinstimmen.

3)Um diese Gleichheit sicherzustellen, werden alle solche Deklarationen üblicherweise in so genannten Header-Dateien zusammengefasst.
a) Eine Header-Datei hat die Namensendung (Dateinamenserweiterung) „h“, z.B.: xxxx.h
b) Die Deklarationen von Header-Dateien werden dann durch eine #include-Anweisung in die Quelltextdateien einkopiert.

4) Definitionen von benutzerdefinierten Datentypen, z.B. Strukturen, müssen in allen Modulen auch gleich lauten. Deswegen werden solche Definitionen auch in Header-Dateien zusammengefasst.


Inhalte der Header-Dateien


Üblicherweise nimmt man in eine Header-Datei folgende Deklarationen auf.

Deklaration Beispiel
Variablendeklarationen extern int i;
Funktionsprototypen int next(int x);
Konstanten const int max=100;
Include-Anweisungen #include <stdio.h>
Makro-Definitionen #define MAX 100
Kommentare // no comment


Außerdem nimmt man auch Deklarationen mit typedef, Klassendefinitionen, Aufzählungstypen, bedingte Kompilation u.ä. auf.

Dagegen nimmt man Definitionen von Variablen und Funktionen nicht in eine Header-Datei auf.


Typische Modulstruktur


Ein Modul (Übersetzungseinheit) wird normalerweise als zwei Dateien hergestellt:

1) Eine Header-Datei bildet eine Schnittstelle des Moduls. Sie enthält Deklarationen von Funktionen, Deklarationen von Daten und ihre ausführliche Benutzeranleitung als Kommentar.

2) Eine Implementierungsdatei (Quelltextdatei) enthält Definitionen von entsprechenden Funktionen und Daten.
Anstelle einer Quelltextdatei kann man aber auch eine Objekt-Datei oder eine Bibliothek in ein Projekt aufnehmen.

Header-Datei (Schnittstelle, Interface)
Quelltextdatei oder Objekt-Datei (Implementierung, Rumpf)



Beispiel


Eine Übersetzungseinheit heißt eine Anwendung, wenn sie Daten oder Funktionen einer anderen Übersetzungseinheit verwendet.
Definition, Deklaration und Anwendung müssen übereinstimmen.

 (image: http://ife.erdaxo.de/uploads/ProzProg8GetrennteUebersetzung/pp54.gif)

⇒ Demo 2


Inkonsistenz


Die getrennte Übersetzung hat auch Nachteile.

Wenn Deklaration und Definition einer Funktion in verschiedenen Übersetzungseinheiten stehen und z.B. wegen eine falschen Korrektur nicht zusammen passen, dann sind sie inkonsistent.

Eine Inkonsistenz bedeutet eine Widersprüchlichkeit zwischen den Daten.

Damit der Compiler die Konsistenz mancher Deklarationen prüfen kann, muss die entsprechende Header-Datei auch
in der Implementierungsdatei eingefügt werden.

⇒ Demo 3


CategoryProzeduraleProgrammierung
Diese Seite wurde noch nicht kommentiert.
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki