Prototipi di funzioni

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

Sintassi

declaration:
declaration-specifiersattribute-seqOptareinit-declarator-listOptare;

/* attribute-seqopt is Microsoft-specific */

declaration-specifiers:
storage-class-specifierdeclaration-specifiersOptare
type-specifierdeclaration-specifiersOptare
type-qualifierdeclaration-specifiersOptare

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

init-declarator:
declarator
declarator = initializer

declarator:
pointerOptaredirect-declarator

direct-declarator: /* Un dichiaratore di funzioni */
direct-declarator(parameter-type-list) /* Dichiaratore in stile nuovo */
direct-declarator(identifier-listOptare) /* Dichiaratore in stile obsoleto */

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

I prototipi di funzione hanno gli utilizzi importanti elencati di seguito:

  • Stabiliscono il tipo restituito per funzioni che restituiscono tipi diversi da int. Anche se le funzioni che restituiscono int valori non richiedono prototipi, i prototipi sono consigliati.

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

  • I prototipi sono utilizzati per inizializzare i puntatori a funzioni prima che quelle funzioni vengano 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. Un tipo non corrispondente tra un argomento e un parametro può determinare che gli argomenti nello stack siano interpretati erroneamente. Ad esempio, in un computer a 16 bit, se un puntatore a 16 bit viene passato come argomento, 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 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 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 parametro complete (int a) possono essere combinate con dichiaratori astratti (int) nella stessa dichiarazione. Ad esempio, la seguente dichiarazione è valida:

int add( int a, int );

Il prototipo può includere sia il tipo di e un identificatore per ogni espressione passata come argomento. Tuttavia, tali identificatori sono solo nell'ambito fino alla fine della dichiarazione. Il prototipo può inoltre riflettere il fatto che il numero di argomenti sia variabile o che nessun argomento sia passato. Senza un elenco di questo tipo, le mancate corrispondenze potrebbero non essere rivelate, pertanto il compilatore non può generare messaggi di diagnostica relativi a essi. 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, quando si compila con /Za per la conformità ANSI, non è possibile chiamare questa funzione senza ottenere un errore di mancata corrispondenza del tipo:

void func1( struct S * );

Per correggere il codice, definire o dichiarare o nell'ambito structunion globale prima del prototipo di funzione:

struct S;
void func1( struct S * );

In /Ze, il tag viene ancora immesso nell'ambito globale.

Vedi anche

Funzioni