Condividi tramite


Prototipi di funzioni

Una dichiarazione di funzione precede la definizione della funzione e specifica il nome, il tipo restituito, la classe di archiviazione e altri attributi di una funzione. Per essere un prototipo, la dichiarazione di funzione deve anche stabilire tipi e identificatori per gli argomenti della funzione.

Sintassi

declaration:
declaration-specifiers attribute-seq optareinit-declarator-listoptare;

/* attribute-seq opt è specifico di Microsoft */

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

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

init-declarator:
declarator
declarator = initializer

declarator:
pointer optaredirect-declarator

direct-declarator: /* Dichiaratore di funzione */
direct-declarator ( parameter-type-list ) /* Dichiaratore di nuovo stile */
direct-declarator ( identifier-list optare) /* Dichiaratore di stile obsoleto */

Il prototipo ha la stessa forma della definizione della funzione, ad eccezione del fatto che termina con un punto e virgola immediatamente dopo la parentesi di chiusura e pertanto non ha corpo. In entrambi i casi, il tipo restituito deve accettare il tipo restituito specificato nella definizione della funzione.

I prototipi di funzione hanno i seguenti usi importanti:

  • Stabiliscono il tipo restituito per le funzioni che restituiscono tipi diversi da int. Anche se le funzioni che restituiscono int valori non richiedono prototipi, è consigliabile usare prototipi.

  • Senza prototipi completi, vengono effettuate conversioni standard, ma non viene effettuato alcun tentativo di controllare il tipo o il numero di argomenti con il numero di parametri.

  • I prototipi vengono usati per inizializzare i puntatori alle funzioni prima che tali funzioni siano definite.

  • L'elenco di parametri viene usato per verificare che gli argomenti nella chiamata di funzione corrispondano ai parametri nella definizione della funzione.

Il tipo convertito di ogni parametro determina l'interpretazione degli argomenti che la chiamata di funzione inserisce nello stack. Una mancata corrispondenza di tipo tra un argomento e un parametro può causare l'errata interpretazione degli argomenti nello stack. Ad esempio, in un computer a 16 bit, se un puntatore a 16 bit viene passato come argomento, quindi dichiarato come long parametro, i primi 32 bit nello stack vengono interpretati come long parametro. Questo errore crea problemi non solo con il long parametro , ma con tutti i parametri successivi. È possibile rilevare gli errori di questo tipo dichiarando prototipi di funzione completi per tutte le funzioni.

Un prototipo stabilisce gli attributi di una funzione. Le chiamate di funzione che precedono la definizione della funzione (o che si verificano in altri file di origine) possono quindi essere controllate per verificare la mancata corrispondenza tra tipo di argomento e tipo restituito. Ad esempio, se si specifica l'identificatore static di classe di archiviazione in un prototipo, è necessario specificare anche la static classe di archiviazione nella definizione della funzione.

Le dichiarazioni di parametri complete (int a) possono essere combinate con dichiaratori astratti (int) nella stessa dichiarazione. Ad esempio, la dichiarazione seguente è valida:

int add( int a, int );

Il prototipo può includere sia il tipo di che un identificatore per ogni espressione passata come argomento. Tuttavia, tali identificatori sono inclusi nell'ambito solo fino alla fine della dichiarazione. Il prototipo può anche riflettere il fatto che il numero di argomenti è variabile o che non vengono passati argomenti. Senza un elenco di questo tipo, le mancate corrispondenze potrebbero non essere rivelate, quindi il compilatore non può generare messaggi di diagnostica relativi. Per altre informazioni sul controllo dei tipi, vedere Argomenti.

L'ambito del prototipo nel compilatore Microsoft C è ora conforme a ANSI durante la compilazione con l'opzione del /Za compilatore. Se si dichiara un struct tag o union all'interno di un prototipo, il tag viene immesso in tale ambito anziché nell'ambito globale. Ad esempio, durante la compilazione con /Za per la conformità ANSI, non è possibile chiamare questa funzione senza ricevere un errore di mancata corrispondenza del tipo:

void func1( struct S * );

Per correggere il codice, definire o dichiarare o union nell'ambito struct globale prima del prototipo della funzione:

struct S;
void func1( struct S * );

In /Zeil tag viene ancora immesso nell'ambito globale.

Vedere anche

Funzioni