Deklarationen in C
Alle bisher vorgestellten Definitionen sind auch Deklarationen. Eine Deklaration legt den Typ eines Bezeichners fest. Eine Definition legt darüber hinaus auch fest, an welche Entität ein Bezeichner gebunden ist, sie definiert also den Bezeichner. Es gibt aber auch Deklarationen, die keine Definitionen sind. Solche Deklarationen werden auch reine Deklarationen genannt. Diese geben nur den Typ eines Bezeichners an, ohne dem Bezeichner eine Entität zuzuordnen. Bei einer Funktionsdeklaration der hier vorgestellten Form sagt man auch, solch eine Deklaration lege den Prototyp einer Funktion fest, um zu sagen, daß der Leser nun ihren Typ kennt. Zusammen mit der Angabe der nötigen Kopfspezifikation bildet eine Deklaration auch die Synopse.
Mindestens der Typ eines Bezeichners muß bei Verwendung des Bezeichners bekannt sein, damit der Leser des Programmes (z.B. der Übersetzer) prüfen kann, ob die Verwendung korrekt hinsichtlich des Typs ist, ohne zuerst die gesamte (restliche) Datei lesen zu müssen. Soll ein Bezeichner erst nach der Verwendung im Quelltext definiert werden, dann muß er also vor der Verwendung zumindestens deklariert werden.
In dem folgenden Beispielprogramm wird die Funktion "hallo" zunächst ohne Definition deklariert. Dabei wird nur der Typ festgelegt. Die Funktion kann dann verwendet werden, weil der Übersetzer ihren Typ nun kennt. Erst nach der ersten Verwendung folgt weiter unten im Quelltext die Definition (Implementation). Der Übersetzer liest den Quelltext nur einmal von vorne bis hinten durch. Erst der Binder wird dann die Adresse der Funktion "hallo" an den Stellen des Aufrufs dieser Funktion einsetzen, das ermöglicht dann den Aufruf, obwohl die Funktion an bei der Verwendung noch nicht definiert ist. Der Binder kann solch Ersetzungen auch dann erzeugen, wenn eine Definition erst nach der Verwendung erfolgt.
Es ist erlaubt, einen Bezeichner mehrfach zu deklarieren, wenn alle Deklarationen übereinstimmen. Eine Definition eines Bezeichners darf jedoch in der Regel nur einmal innerhalb eines Gültigkeitsbereichs erfolgen.
deklaration.c
#include <stdio.h>
void hallo( void ); // Deklaration von "hallo" (ohne Definition)
int main(){
hallo // Verwendung von "hallo"
(); }
void hallo( void ); // identische Redeklaration ist erlaubt
void hallo( void ) // Definition und erneute Deklaration von "hallo"
{ printf( "Hallo!\n" ); } //stdout
Hallo!
Das Schlüsselwort "void" in den runden Klammern nach dem Funktionsnamen kann bei der Definition einer Funktion entfallen. Daher wird es in der Übersetzungseinheit "deklaration.c" bei der Definition der Funktion "hallo" nicht verwendet, obwohl das auch erlaubt wäre, ohne daß sich dadurch an der Bedeutung etwas verändert.
Ohne die Deklaration kennte der C -Leser die Funktion beim Aufruf nicht gut genug, um die Richtigkeit ihrer Verwendung zu prüfen.
deklaration.txt
#include <stdio.h>
int main( void ){ hallo(); }
void hallo( void ){ printf( "Hallo!\n" ); }Konsole
"deklaration.txt", line 2: error: identifier "hallo" is undefined
int main( void ){ hallo(); }
^
1 error detected in the compilation of "deklaration.txt".
Natürlich könnte der Eindruck entstehen, daß reine Deklarationen nicht so dringend benötigt werden, weil Funktionen ja immer vor ihrer Verwendung definiert werden können. In anderen Lektionen wird sich aber zeigen, daß dies nicht immer möglich ist und, daß reine Deklarationen oft eine wichtige Rolle spielen.
Leere Klammern oder Schlüsselwort "void"?
Sowohl in einer Definition als auch in einer reinen Deklaration können die runden Klammern leer sein oder das Schlüsselwort "void" enthalten, aber die verschiedenen Möglichkeiten bedeuten nicht immer das gleiche.
In einer Definition einer Funktion ohne Parameter kann das Paar runder Klammern leer gelassen werden oder das Schlüsselwort "void" enthalten. In beiden Fällen wird eine Funktion ohne Parameter definiert, doch nur bei Verwendung des Schlüsselwortes "void" wird ein „Prototyp“ definiert, durch den nachfolgende Aufrufe mit Argumenten als falsch gelten. Daher sollte hier das Schlüsselwort "void" verwendet werden.
Soll eine Funktion ohne Parameter mit einer reinen Deklaration festgelegt werden, muß das Schlüsselwort "void" in den runden Klammern stehen.
Wenn in einer reinen Deklaration einer Funktion leere Klammern verwendet werden, dann wird damit keine Aussage über die Parameter der Funktion gemacht. Dieses Schreibweise ist veraltet und soll vermieden werden.
Beispiele für die richtige Verwendung finden sich bereits weiter oben.