Funktionsprototypen
Eine Funktionsdeklaration ist der Funktionsdefinition vorangestellt und gibt den Namen, Rückgabetyp, die Speicherklasse und andere Attribute einer Funktion an. Um als Prototyp zu fungieren, muss die Funktionsdeklaration auch Typen und Bezeichner für die Argumente der Funktion festlegen.
Syntax
declaration
:
declaration-specifiers
attribute-seq
optinit-declarator-list
opt;
/* attribute-seq
opt ist Microsoft-spezifisch */
declaration-specifiers
:
storage-class-specifier
declaration-specifiers
opt
type-specifier
declaration-specifiers
opt
type-qualifier
declaration-specifiers
opt
init-declarator-list
:
init-declarator
init-declarator-list
,
init-declarator
init-declarator
:
declarator
declarator
=
initializer
declarator
:
pointer
optdirect-declarator
direct-declarator
: /* Ein Funktionsdeklarator */
direct-declarator
(
parameter-type-list
)
/* Deklarator im neuen Format */
direct-declarator
(
identifier-list
opt)
/* Deklarator im veralteten Format */
Der Prototyp hat das gleiche Format wie die Funktionsdefinition. Allerdings wird er mit einem Semikolon unmittelbar nach der schließenden Klammer beendet und enthält dementsprechend keinen Textkörper. In jedem Fall muss der Rückgabetyp dem Rückgabetyp entsprechen, der in der Funktionsdefinition angegeben wird.
Funktionsprototypen haben die folgenden wichtigen Verwendungen:
Sie legen den Rückgabetyp für Funktionen fest, die andere Typen als
int
zurückgeben. Obwohl Funktionen, dieint
-Werte zurückgeben, keine Prototypen erfordern, werden Prototypen empfohlen.Ohne vollständige Prototypen werden Standardkonvertierungen ausgeführt, es wird jedoch nicht versucht, Typ oder Anzahl der Argumente anhand der Anzahl der Parameter zu überprüfen.
Prototypen werden verwendet, um Zeiger auf Funktionen zu initialisieren, bevor diese Funktionen definiert werden.
Die Parameterliste wird verwendet, um zu überprüfen, ob die Argumente im Funktionsaufruf mit den Parametern in der Funktionsdefinition übereinstimmen.
Der konvertierte Typ jedes Parameters bestimmt die Interpretation der Argumente, die der Funktionsaufruf auf dem Stapel ablegt. Ein Typenkonflikt zwischen einem Parameter und einem Argument kann verursachen, dass Argumente auf dem Stapel fehlinterpretiert werden. Wenn beispielsweise auf einem 16-Bit-Computer ein 16-Bit-Zeiger als Argument übergeben und dann als long
-Parameter deklariert wird, werden die ersten 32 Bit im Stapel als long
-Parameter interpretiert. Dieser Fehler verursacht nicht nur Probleme mit dem long
-Parameter, sondern auch mit allen nachfolgenden Parametern. Sie können Fehler dieser Art erkennen, indem Sie vollständige Funktionsprototypen für alle Funktionen deklarieren.
Ein Prototyp legt die Attribute einer Funktion fest. Anschließend können Funktionsaufrufe, die der Funktionsdefinition vorangehen (oder in anderen Quelldateien auftreten), auf Konflikte mit Argument- und Rückgabetypen überprüft werden. Wenn Sie beispielsweise den Speicherklassenspezifizierer static
in einem Prototyp angeben, müssen Sie die static
-Speicherklasse auch in der Funktionsdefinition angeben.
Vollständige Parameterdeklarationen (int a
) können mit abstrakten Deklaratoren (int
) in der gleichen Deklaration kombiniert werden. Die folgende Deklaration ist beispielsweise gültig:
int add( int a, int );
Der Prototyp kann sowohl den Typ als auch den Bezeichner für jeden Ausdruck beinhalten, der als Argument übergeben wird. Solche Bezeichner befinden sich jedoch nur bis zum Ende der Deklaration im Gültigkeitsbereich. Der Prototyp reflektiert auch die Tatsache, dass die Anzahl der Argumente variabel ist oder dass keine Argumente übergeben werden. Ohne eine solche Liste können Konflikte nicht aufgedeckt werden, sodass der Compiler keine entsprechenden Diagnosemeldungen generieren kann. Weitere Informationen zur Typüberprüfung finden Sie unter Argumente.
Der Prototypbereich im Microsoft C-Compiler ist beim Kompilieren mit der Compileroption /Za
jetzt ANSI-konform. Wenn Sie ein struct
- oder union
-Tag in einem Prototyp deklarieren, wird das Tag in diesem Gültigkeitsbereich eingetragen, nicht im globalen Gültigkeitsbereich. Zum Beispiel können Sie bei der Kompilierung mit /Za
für ANSI-Konformität diese Funktion nicht aufrufen, ohne einen Typenkonfliktfehler zu verursachen:
void func1( struct S * );
Definieren oder deklarieren Sie struct
oder union
im globalen Bereich vor dem Funktionsprototyp, um den Code zu korrigieren:
struct S;
void func1( struct S * );
Unter /Ze
wird das Tag weiterhin im globalen Gültigkeitsbereich eingegeben.
Siehe auch
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für