Prototipi di funzione

  • 11/04/2016
  • 3 minuti per leggere
    • c
    • v
    • n
    • M
    • g
    • +1

Una dichiarazione di funzione precede la definizione della funzione e ne specifica il nome, tipo di ritorno, classe di memorizzazione 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

dichiarazione:
dichiarazione-specificatori attributo-seqopt init-declarator-listopt ;

/* attributo-seqopt è specifico di Microsoft */

dichiarazione-specificatori:
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 = inizializzatore

declarator:
pointeropt direct-declarator

direct-declarator: /* Un dichiaratore di funzione */
direct-declarator ( parameter-type-list ) /* Nuovo dichiaratore di stile */
direct-declarator ( identifier-listopt ) /* Dichiaratore di stile obsoleto */

Il prototipo ha la stessa forma della definizione di funzione, tranne che è terminato da un punto e virgola subito dopo la parentesi di chiusura e quindi non ha corpo. In entrambi i casi, il tipo di ritorno deve concordare con il tipo di ritorno specificato nella definizione della funzione.

I prototipi di funzione hanno i seguenti importanti usi:

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

  • Senza prototipi completi, le conversioni standard sono fatte, ma nessun tentativo è fatto per controllare il tipo o il numero di argomenti con il numero di parametri.

  • I prototipi sono usati per inizializzare i puntatori alle funzioni prima che queste funzioni siano definite.

  • La lista dei parametri è usata per controllare la corrispondenza degli argomenti nella chiamata di funzione con i parametri nella definizione della funzione.

Il tipo convertito di ogni parametro determina l’interpretazione degli argomenti che la chiamata di funzione mette sullo stack. Una mancata corrispondenza di tipo tra un argomento e un parametro può causare un’errata interpretazione degli argomenti sullo stack. Per esempio, su un computer a 16 bit, se un puntatore a 16 bit viene passato come argomento, poi dichiarato come parametro long, i primi 32 bit sullo stack vengono interpretati come un parametro long. Questo errore crea problemi non solo con il parametro long, ma con tutti i parametri che lo seguono. Potete rilevare errori di questo tipo dichiarando prototipi di funzione completi per tutte le funzioni.

Un prototipo stabilisce gli attributi di una funzione in modo che le chiamate alla funzione che precedono la sua definizione (o che avvengono in altri file sorgente) possano essere controllate per la mancata corrispondenza del tipo di argomento e del tipo di ritorno. Per esempio, se si specifica lo specificatore static della classe di archiviazione in un prototipo, è necessario specificare anche la classe di archiviazione static nella definizione della funzione.

Le dichiarazioni complete di parametri (int a) possono essere mescolate con i dichiaratori astratti (int) nella stessa dichiarazione. Per esempio, la seguente dichiarazione è legale:

int add( int a, int );

Il prototipo può includere sia il tipo che un identificatore per ogni espressione che viene passata come argomento. Tuttavia, tali identificatori hanno uno scopo 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 tale elenco, le discordanze potrebbero non essere rivelate, quindi il compilatore non può generare messaggi diagnostici al riguardo. Vedere Argomenti per maggiori informazioni sul controllo dei tipi.

Lo scopo del prototipo nel compilatore Microsoft C è ora conforme all’ANSI quando si compila con l’opzione /Za del compilatore. Questo significa che se dichiarate un tag struct o union all’interno di un prototipo, il tag viene inserito in quell’ambito piuttosto che in quello globale. Per esempio, quando si compila con /Za per la conformità ANSI, non si può mai chiamare questa funzione senza ottenere un errore di type mismatch:

void func1( struct S * );

Per correggere il codice, definire o dichiarare il struct o union nello scope globale prima del prototipo della funzione:

struct S;void func1( struct S * );

Sotto /Ze, il tag è ancora inserito nello scope globale.

Vedi anche

Funzioni

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.