- 11/04/2016
- 3 minuten om te lezen
-
- c
- v
- n
- M
- g
-
+1
Een functiedeclaratie gaat vooraf aan de functiedefinitie en specificeert de naam, terugkeertype, opslagklasse en andere attributen van een functie. Om een prototype te zijn, moet de functiedeclaratie ook typen en identifiers voor de argumenten van de functie vaststellen.
Syntax
declaration:
declaration-specifiers attribute-seqopt init-declarator-listopt ;
/* attribute-seqopt is Microsoft-specifiek */
declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
declarator:
pointeropt direct-declarator
direct-declarator: /* Een functie declarator */
direct-declarator ( parameter-type-list ) /* Nieuwe-stijl declarator */
direct-declarator ( identifier-listopt ) /* Obsolete-stijl declarator */
Het prototype heeft dezelfde vorm als de functiedefinitie, behalve dat het wordt afgesloten met een puntkomma onmiddellijk na de afsluitende haakjes en daarom geen body heeft. In beide gevallen moet het terugkeertype overeenkomen met het terugkeertype dat in de functiedefinitie is opgegeven.
Functieprototypen hebben de volgende belangrijke toepassingen:
-
Zij bepalen het terugkeertype voor functies die andere types dan
int
teruggeven. Hoewel functies dieint
-waarden retourneren geen prototypen nodig hebben, worden prototypen wel aanbevolen. -
Zonder volledige prototypen worden standaardconversies uitgevoerd, maar wordt geen poging gedaan om het type of het aantal argumenten te controleren met het aantal parameters.
-
Prototypen worden gebruikt om pointers naar functies te initialiseren voordat deze functies zijn gedefinieerd.
-
De parameterlijst wordt gebruikt om te controleren of de argumenten in de functieaanroep overeenkomen met de parameters in de functiedefinitie.
Het geconverteerde type van elke parameter bepaalt de interpretatie van de argumenten die de functieaanroep op de stack plaatst. Een type-afwijking tussen een argument en een parameter kan ertoe leiden dat de argumenten op de stack verkeerd worden geïnterpreteerd. Als bijvoorbeeld op een 16-bits computer een 16-bits pointer wordt doorgegeven als argument en vervolgens wordt gedeclareerd als een long
-parameter, worden de eerste 32 bits op de stack geïnterpreteerd als een long
-parameter. Deze fout creëert niet alleen problemen met de long
parameter, maar met alle parameters die er op volgen. U kunt dit soort fouten opsporen door volledige functieprototypen voor alle functies te declareren.
Een prototype legt de attributen van een functie vast, zodat aanroepen naar de functie die voorafgaan aan de definitie (of in andere bronbestanden voorkomen) kunnen worden gecontroleerd op argument-type en return-type mismatches. Bijvoorbeeld, als u de static
opslag-klasse specificier in een prototype specificeert, moet u ook de static
opslag-klasse in de functiedefinitie specificeren.
Volledige parameter declaraties (int a
) kunnen worden gemengd met abstracte declaratoren (int
) in dezelfde declaratie. Bijvoorbeeld, de volgende declaratie is legaal:
int add( int a, int );
Het prototype kan zowel het type van, als een identifier voor, elke expressie bevatten die als argument wordt doorgegeven. Dergelijke identifiers hebben echter alleen bereik tot het einde van de declaratie. Het prototype kan ook het feit weergeven dat het aantal argumenten variabel is, of dat er geen argumenten worden doorgegeven. Zonder zo’n lijst worden mismatches misschien niet onthuld, zodat de compiler er geen diagnostische boodschappen over kan genereren. Zie Argumenten voor meer informatie over type-controle.
Prototype scope in de Microsoft C compiler is nu ANSI-compliant als er gecompileerd wordt met de /Za compiler optie. Dit betekent dat als u een struct
of union
tag declareert binnen een prototype, de tag wordt ingevoerd in dat bereik in plaats van in het globale bereik. Bijvoorbeeld, wanneer u compileert met /Za voor ANSI compliancy, kunt u nooit deze functie aanroepen zonder een type mismatch fout te krijgen:
void func1( struct S * );
Om uw code te corrigeren, definieer of declareer de struct
of union
op globaal bereik voor het functie prototype:
struct S;void func1( struct S * );
Onder /Ze, wordt de tag nog steeds op globaal bereik ingevoerd.
Zie ook
Functies