- 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 returnererint
-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