Deklarationen und Prototypen

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Funktionen - Index

Bei Kernighan und Ritchie kann eine Funktion implizit durch ihr Vorhandensein in einem Funktionsaufruf oder wie folgt explizit deklariert werden:

<type> func();

wobei type der optionale Rückgabewert mit der Voreinstellung int ist. In C++ bedeutet diese Deklaration <type> func(void). Eine Funktion kann so deklariert werden, dass sie einen beliebigen Typ mit Ausnahme eines Arrays oder einer Funktion liefert. Bei diesem Konzept kann der Compiler nicht überprüfen, ob der Typ oder die Anzahl der Argumente in dem Funktionsaufruf mit der Deklaration übereinstimmen.

Dieses Problem wurde durch die Einführung von Funktionsprototypen mit folgender Deklarationssyntax behoben:

<type> func(Parameter-Deklaratorliste);

Anmerkung:  Sie können innerhalb der IDE oder mit dem Kommandozeilen-Compiler eine Warnung aktivieren: "Function called without a prototype."

Deklaratoren legen den Typ für jeden Funktionsparameter fest. Der Compiler verwendet diese Information, um den Funktionsaufruf auf seine Gültigkeit hin zu überprüfen. Der Compiler kann dann auch Argumente in den benötigten Typ konvertieren. Nehmen wir an, Sie haben folgendes Programmfragment geschrieben:

extern long lmax(long v1, long v2); /* Prototyp */
foo()
{
   int limit = 32;
   char ch = 'A';
   long mval;
   mval = lmax(limit,ch);    /* Funktionsaufruf */
}

Da das Programm für lmax einen Funktionsprototyp hat, werden limit und ch – gemäß den gebräuchlichen Konvertierungsregeln – in den Typ long konvertiert, bevor sie für den Aufruf von lmax auf dem Stack abgelegt werden. Ohne Funktionsprototyp würden limit und ch als Integer und Zeichen auf den Stack gelegt. In diesem Fall würden die vom Stack an lmax übergebenen Werte in Größe und Inhalt nicht der von lmax erwarteten Übergabe entsprechen – und dies würde zu Problemen führen. Die klassische Deklaration lässt keine Überprüfung des Parametertyps und der Parameteranzahl zu. Deshalb ist der Einsatz von Funktionsprototypen eine große Hilfe bei der Fehlersuche.

Funktionsprototypen unterstützen auch die Programmdokumentation. Die Funktion strcpy übernimmt zwei Parameter: Einen Quell-String und einen Ziel-String. Die Frage ist, welcher ist welcher? Der Funktionsprototyp

char *strcpy(char *dest, const char *source);

beantwortet diese Frage. Befinden sich die Funktionsprototypen in einer Header-Datei, dann können Sie sich diese Include-Datei ausdrucken lassen. Damit steht Ihnen der größte Teil der Informationen zur Verfügung, die Sie in Ihrem Programm für den Aufruf dieser Funktionen benötigen. Wenn ein Prototyp-Parameter einen Bezeichner enthält, wird dieser nur für spätere Fehlermeldungen benutzt, die diesen Parameter betreffen; ansonsten wird er nicht verwendet.

Ein Funktionsdeklarator, der nur das Wort void in Klammern umfasst, repräsentiert eine Funktion, die keine Argumente benötigt:

func(void);

In C++ reicht hierzu die Deklaration func() aus.

Ein Funktionsprototyp deklariert normalerweise eine Funktion mit einer festen Anzahl von Parametern. Bei Funktionen, die eine unterschiedliche Anzahl von Parametern haben können (wie zum Beispiel printf), endet der Funktionsprototyp mit einem Auslassungszeichen (...), zum Beispiel:

f(int *count, long total, ...);

Bei dieser Art Prototyp werden die festen Parameter während des Compilierens überprüft und die variablen Parameter ohne Typ-Prüfung weitergegeben.

Anmerkung:  stdarg.h und varargs.h enthalten Makros, die Sie in selbstdefinierten Funktionen mit variabler Parameteranzahl verwenden können.

Im folgenden finden Sie einige weitere Beispiele für Funktionsdeklaratoren und Prototypen:

int f();                     /* In C liefert diese Funktion einen 
                               int ohne Informationen über Parameter.
                               Dies ist klassischer K&R-Stil */
int f();                     /* In C++ eine Funktion ohne Argumente */
int f(void);                 /* Eine Funktion ohne Parameter,
                               die int liefert. */
int  p(int,long);            /* Eine Funktion, die int liefert und 
                               zwei Parameter akzeptiert:
                               - der erste ein int;
                               - der zweite ein long. */
int __pascal q(void);        /* Eine Pascal-Funktion ohne Parameter,
                               die einen int liefert. */
int printf(char *format,...);  /*Eine Funktion, die einen int liefert
                               und einen festen Char-Parameter 
                               und zusätzliche Argumente unbekannten
                               Typs erwartet. */
int (*fp)(int)               /* Ein Zeiger auf eine Funktion, die einen
                               int liefert und einen einzelnen 
                               int-Parameter erwartet. */