Community
 
Aggiungi lista preferiti Aggiungi lista nera Invia ad un amico
------------------
Crea
Profilo
Blog
Video
Sito
Foto
Amici
   
 
 

Linguaggio C - Funzioni

La definizione e la dichiarazione di una funzione puo' essere sviluppata o in base alla sintassi definita nella versione originale del linguaggio C, oppure sulla base della successiva versione ANSI del linguaggio.

Definizione

La definizione di una funzione basata sulla specifica iniziale della sintassi del linguaggio, si presenta nella seguente forma:
  tiporitornato nomefunzione(lista_parametri_formali)
                  dichiarazione_parametri_formali
    {
    definizioni/dichiarazioni

    lista_statement
    }
    

Se il tiporitornato non viene specificato, per default viene assunto di tipo int.
Se la funzione non ritorna alcun risultato. allora tiporitornato deve essere specificato di tipo void.

Esempio di definizione:

  int fattoriale(n)
        int n;
    {
    if (n > 1)
      return n*fattoriale(n-1);
    else
      return 1;
    }
    

La definizione della funzione effettuata in base alle specifiche della versione ANSI del linguaggio C, assume la forma:

  tiporitornato nomefunzione(dichiarazione_parametri_formali)
    {
    definizioni/dichiarazioni

    lista_statement
    }
    

Se la funzione non accetta parametri, la dichiarazione_parametri_formali deve essere specificata di tipo void.
Esempio:

int funzione_senza_parametri(void)

Esempio di definizione:

  int fattoriale(int n)
    {
    if (n > 1)
      return n*fattoriale(n-1);
    else
      return 1;
    }
    

Indipendentemente dai 2 modi di definizione della funzione, essa ha termine al verificarsi di una delle condizioni:
o viene esguita l'istruzione return
o l'ultima istruzione del corpo della funzione e' stata eseguita
Quando la funzione termina, il controllo torna al chiamante.

Una funzione puo' essere invocata tramite il codice:

  nomefunzione(lista_parametri_attuali)
    

N. B. - Il C non specifica l'ordine di valutazione dei parametri attuali, pertanto bisogna prestare attenzione affinche' gli effetti collaterali non intervengano su variabili utilizzate anche per altri parametri.
Esempio di chiamata ERRATA:

  int j=0;
  ...
  funzione(j=5, j+1);           /* ERRATA */
                                /* Puo' venire eseguita la valutazione di
                                 * j+1, prima dell'assegnamento j=5 !!!
                                 * (dipende dalla implementazione del
                                 * compilatore) */
    

 

Dichiarazione

Nela versione originale del linguaggio la dichiarazione si presenta con la sintassi seguente:
  tiporisultato nomefunzione();    
    

mentre nella versione ANSI, appare il concetto di prototype della funzione, attraverso il quale viene effettuato il controllo del tipo dei parametri passati durante la chiamata della funzione.
Il controllo e' effettuato al tempo di compilazione e questo costituisce, senza dubbio, un notevole vantaggio.
Il prototype presenta la sintassi seguente:

  tiporisultato nomefunzione(dichiarazione_parametri_formali);    
    

Qualora la funzione non accetti parametri, la dichiarazione_parametri_formali deve essere definita come void.

In entrambe le situazioni, la dichiarazione della funzione e' necessaria se viene invocata prima della sua definizione, oppure se e' definita in altro file e compilata separatamente.

Funzioni vs. puntatori

Il linguaggio C consente di dichiarare e/o definire, oltre alle funzioni, anche i puntatori alle funzioni.
Ad essi possono essere assegnati gli indirizzi di altre funzioni, poiche' il tipo della funzione abbia lo stesso tipo della funzione puntata, cioe' che il puntatore punti ad un tipo di funzione con gli stessi parametri formali (per numero, posizione e tipo) e abbia lo stesso tipo di risultato, rispetto alla funzione di cui si vuole assegnare l'indirizzo.
Inoltre i puntatori a funzione possono essere dereferenziati allo scopo di eseguire il codice della funzione a cui puntano.

Inoltre il C considera il nome della funzione come il puntatore al suo codice, per cui non occorre applicare gli operatori indirizzo & e indirezione *, sebbene il linguaggio ne permetta anche il loro impiego.
Esempio:

  int funz(int a);              /* prototype funzione */

  int (*pf)(int);               /* pf e' puntatore ad una funzione, avente un
                                 * parametro di tipo int e ritorna un int, cioe'
                                 * int f(int) */

  ...

  pf = &funz;                   /* oppure pf = funz; */
  (*pf)(5);                         /* oppure pf(5); */
    

Facendo uso di puntatori, anche le funzioni possono far parte dei parametri di una funzione e possono essere restituite come risultato di una funzione.
Data l'equivalenza tra il puntatore della funzione ed il suo nome, anche per questi casi e' possibile impiegare semplicemente il nome della funzione, senza far uno dell'operando indirizzo.

Vedi un esempio di sorgente

Passaggio di parametri

Nel C il passaggio dei paramteri ad una funzione, avviene sempre per valore, per cui non e' possibile che una funzione abbia degli effetti collaterali sui parametri passati.
Esempio: #include <stdio.h> #include <stdlib.h> void funz(int a); int main(int argc, char *argv) { int a=10; printf("a = %d\n\n", a); /* stampa "a = 10" */ funz(a); printf("a = %d\n\n", a); /* stampa ancora "a = 10" */ return 0; } void funz(int a) { a/=2; printf("a = %d\n\n", a); /* stampa "a = 5" */ }

Qualora, invece, sia proprio necessario che la chiamata di una funzione produca degli effetti collaterali, allora diventa indispensabile passare alla funzione gli indirizzi di memoria di dove si devono ottenere gli effetti collaterali. In altri termini vengono passati alla funzione gli indirizzi degli argomenti per i quali siano richiesti gli effetti collaterali.

In questo modo, i puntatori sono ancora passati per valore, e pertanto non possono essere modificati dalla funzione, mentre puo' venire modificato il contenuto a cui essi puntano.
Esempio:

... int main(int argc, char *argv[]) { int a1, b1, c1; ... inizializza(&a1, &b1, &c1); /* chiamata alla funzione */ ... } void inizializza(int *a, int *b, int *c) { *a = 5; *b = 7; *c = 20; }


Indice-C Indice linguaggio C
At Home Umberto Zappi Home Page