Freigeben über


Funktionsprototypen

Eine Funktionsdeklaration steht vor der Funktionsdefinition und gibt den Namen, den Rückgabetyp, die Speicherklasse und andere Attribute einer Funktion an. Um ein Prototyp zu sein, muss die Funktionsdeklaration auch Typen und Bezeichner für die Argumente der Funktion einrichten.

Syntax

declaration:
declaration-specifiers attribute-seq optiereninit-declarator-listoptieren;

/* attribute-seq opt is Microsoft-specific */

declaration-specifiers:
storage-class-specifier declaration-specifiers optieren
type-specifier declaration-specifiers optieren
type-qualifier declaration-specifiers optieren

init-declarator-list:
init-declarator
init-declarator-list , init-declarator

init-declarator:
declarator
declarator = initializer

declarator:
pointer wählendirect-declarator

direct-declarator: /* Ein Funktions-Deklarator */
direct-declarator ( parameter-type-list ) /* Deklarator des neuen Stils */
direct-declarator ( identifier-list optieren) /* Deklarator des veralteten Stils */

Der Prototyp hat dieselbe Form wie die Funktionsdefinition, mit der Ausnahme, dass er durch ein Semikolon beendet wird, das unmittelbar auf die schließende Klammer folgt und daher keinen Text hat. In beiden Fällen muss der Rückgabetyp mit dem in der Funktionsdefinition angegebenen Rückgabetyp übereinstimmen.

Funktionsprototypen haben die folgenden wichtigen Verwendungsmöglichkeiten:

  • Sie richten den Rückgabetyp für Funktionen ein, die andere Typen als int. Obwohl Funktionen, die Werte zurückgeben int , keine Prototypen erfordern, werden Prototypen empfohlen.

  • Ohne vollständige Prototypen werden Standardkonvertierungen vorgenommen, aber es wird nicht versucht, den Typ oder die Anzahl der Argumente mit 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 Argumente im Funktionsaufruf den Parametern in der Funktionsdefinition entsprechen.

Der konvertierte Typ der einzelnen Parameter bestimmt die Interpretation der Argumente, die der Funktionsaufruf im Stapel platziert. Ein Typkonflikt zwischen einem Argument und einem Parameter kann dazu führen, dass die Argumente im Stapel falsch interpretiert werden. Wenn z. B. auf einem 16-Bit-Computer ein 16-Bit-Zeiger als Argument übergeben wird, long werden die ersten 32 Bit im Stapel als long Parameter interpretiert. Dieser Fehler verursacht nicht nur Probleme mit dem long Parameter, sondern mit allen nachfolgenden Parametern. Sie können Fehler dieser Art erkennen, indem Sie vollständige Funktionsprototypen für alle Funktionen deklarieren.

Ein Prototyp richtet die Attribute einer Funktion ein. Anschließend können Funktionsaufrufe, die vor der Funktionsdefinition stehen (oder in anderen Quelldateien vorkommen), auf Argumenttyp- und Rückgabetypkonflikten überprüft werden. Wenn Sie beispielsweise den static Speicherklassenbezeichner in einem Prototyp angeben, müssen Sie auch die static Speicherklasse in der Funktionsdefinition angeben.

Vollständige Parameterdeklarationen (int a) können in derselben Deklaration mit abstrakten Deklaratoren (int) gemischt werden. Die folgende Erklärung ist z. B. legal:

int add( int a, int );

Der Prototyp kann sowohl den Typ als auch einen Bezeichner für jeden Ausdruck enthalten, der als Argument übergeben wird. Solche Bezeichner befinden sich jedoch nur bis zum Ende der Deklaration im Gültigkeitsbereich. Der Prototyp kann auch die Tatsache widerspiegeln, dass die Anzahl der Argumente variabel ist oder dass keine Argumente übergeben werden. Ohne eine solche Liste werden möglicherweise keine Übereinstimmungen angezeigt, sodass der Compiler keine Diagnosemeldungen zu ihnen generieren kann. Weitere Informationen zur Typüberprüfung finden Sie unter "Argumente".

Der Prototypbereich im Microsoft C-Compiler ist jetzt ANSI-konform, wenn sie mit der /Za Compileroption kompiliert wird. Wenn Sie ein Tag innerhalb union eines struct Prototyps deklarieren, wird das Tag nicht im globalen Bereich, sondern in diesen Bereich eingegeben. Wenn Sie z. B. eine Kompilierung /Za für die ANSI-Konformität ausführen, können Sie diese Funktion nie aufrufen, ohne dass ein Typkonfliktfehler angezeigt wird:

void func1( struct S * );

Um den Code zu korrigieren, definieren oder deklarieren Sie den struct oder union den globalen Bereich vor dem Funktionsprototyp:

struct S;
void func1( struct S * );

Unter /Zewird das Tag weiterhin auf globaler Ebene eingegeben.

Siehe auch

Funktionen