Functie Prototypes

  • 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 die int-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

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.