Funktionsprototyper

  • 11/04/2016
  • 3 minutter at læse
    • c
    • v
    • n
    • M
    • g
    • +1

En funktionsdeklaration går forud for funktionsdefinitionen og angiver navnet, returneringstype, lagringsklasse og andre attributter for en funktion. For at være en prototype skal funktionsdeklarationen også fastlægge typer og identifikatorer for funktionens argumenter for at være en prototype.

Syntaks

declaration:
declaration-specifiers attribute-seqopt init-declarator-listopt ;

/* attribute-seqopt er Microsoft-specifik */

declaration-specifiers:
storage-class-specifier declaration-specifiersopt
typespecifier declaration-specifiersopt
typekvalifier declaration-specifiersopt
typekvalifier declaration-specifiersopt

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

init-declarator:
declarator
declarator = initializer

declarator:
pointeropt direct-declarator

direct-declarator: /* En funktionsdeklarator */
direct-declarator ( parameter-type-list ) /* Deklarator i ny stil */
direct-declarator ( identifier-listopt ) /* Deklarator i forældet stil */

Prototypen har samme form som funktionsdefinitionen, bortset fra, at den afsluttes med et semikolon umiddelbart efter den afsluttende parentes og derfor ikke har nogen krop. I begge tilfælde skal returtypen stemme overens med den returtype, der er angivet i funktionsdefinitionen.

Funktionsprototyper har følgende vigtige anvendelser:

  • De fastlægger returtypen for funktioner, der returnerer andre typer end int. Selv om funktioner, der returnerer int-værdier, ikke kræver prototyper, anbefales prototyper.

  • Og uden komplette prototyper foretages standardkonverteringer, men der gøres ikke forsøg på at kontrollere typen eller antallet af argumenter med antallet af parametre.

  • Prototyper bruges til at initialisere pegepunkter til funktioner, før disse funktioner er defineret.

  • Parameterlisten bruges til at kontrollere overensstemmelsen mellem argumenterne i funktionskaldet og parametrene i funktionsdefinitionen.

Den konverterede type af hver parameter bestemmer fortolkningen af de argumenter, som funktionskaldet placerer på stakken. En typeoverensstemmelse mellem et argument og en parameter kan medføre, at argumenterne på stakken fejlfortolkes. Hvis der f.eks. på en 16-bit computer overføres en 16-bit pointer som et argument og derefter deklareres som en long parameter, fortolkes de første 32 bits på stakken som en long parameter på en 16-bit computer. Denne fejl skaber problemer ikke kun med long-parameteren, men også med alle parametre, der følger efter den. Du kan opdage fejl af denne art ved at deklarere fuldstændige funktionsprototyper for alle funktioner.

En prototype fastlægger en funktions attributter, så kald til funktionen, der går forud for dens definition (eller forekommer i andre kildefiler), kan kontrolleres for mismatch mellem argument- og returtype. Hvis du f.eks. angiver specifikationen static storage-klasse i en prototype, skal du også angive static storage-klassen i funktionsdefinitionen.

Fuldstændige parameterdeklarationer (int a) kan blandes med abstrakte deklaratorer (int) i den samme deklaration. F.eks. er følgende deklaration lovlig:

int add( int a, int );

Prototypen kan indeholde både typen af og en identifikator for hvert udtryk, der overgives som argument. Sådanne identifikatorer har dog kun rækkevidde indtil slutningen af erklæringen. Prototypen kan også afspejle det faktum, at antallet af argumenter er variabelt, eller at der ikke overgives nogen argumenter. Uden en sådan liste kan uoverensstemmelser ikke afsløres, og compileren kan derfor ikke generere diagnostiske meddelelser om dem. Se Argumenter for yderligere oplysninger om typekontrol.

Prototype scope i Microsoft C-compileren er nu ANSI-kompatibel, når der kompileres med compilerindstillingen /Za. Det betyder, at hvis du deklarerer et struct– eller union-tag i en prototype, indtastes tagget i det pågældende scope i stedet for i det globale scope. Når du kompilerer med /Za for ANSI-overensstemmelse, kan du f.eks. aldrig kalde denne funktion uden at få en typefejl:

void func1( struct S * );

For at rette din kode skal du definere eller deklarere struct eller union på globalt omfang før funktionsprototypen:

struct S;void func1( struct S * );

Under /Ze indtastes tagget stadig på globalt omfang.

Se også

Funktioner

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.