Livello 6: le funzioni

Le funzioni sono dei sotto-programmi, blocchi di codice che possono essere riutilizzati quando una specifica funzionalità si rende necessaria nel nostro programma e rappresentano il primo passo verso la programmazione modulare. Oltre alle funzioni standard, a quelle accessibili tramite l’uso di librerie esterne, è possibile per il programmatore definire delle funzioni nuove. Una funzione fornisce delle funzionalità alla funzione main (o più in generale alla funzione chiamante) e comunica con questa (/e) attraverso il passaggio dei parametri e la possibilità di restituire un valore (return). Una funzione dovrebbe svolgere una sola attività e quindi generalmente sarà costituita da un ridotto numero di istruzioni. In particolare, ci si aspetta che una funzione sia coesa (svolge poche attività) e che abbia un basso accoppiamento (poca influenza con altre funzioni). Per utilizzare una nuova funzione sono necessarie queste fasi: dichiarazione, chiamata e definizione. Vediamo un semplice esempio:

#include <stdio.h>
int sum(int,int); //dichiarazione

int main() {
  int a=1,b=1,s;

  s=sum(a,b); //chiamata
  printf("\nThe sum is %d\n",s);
}

int sum(int c,int d) { //definizione
  int s;
  s=c+d;
  return s;
}

La dichiarazione int sum(int,int); consente di “presentare” al compilatore la funzione. Serve specificare il nome, il tipo del valore restituito dalla funzione (si usa void nel caso in cui la funzione non debba rendere niente) e i parametri (indispensabile almeno il tipo)(int,int). La chiamata s=sum(a,b); consente di mandare in esecuzione le istruzioni contenute nel corpo della funzione (vedi definizione) passando alla funzione i parametri attuali (a e b in questo caso). La definzione contiene l’insieme di istruzioni che caratterizzano la funzione. Le variabili locali (cioè visibili solo dentro la funzione) c e d sono chiamati parametri formali e vengono inizializzati con i valori dei corrispondenti parametri attuali. In sostanza, in questo caso è come se scrivessimo c = a e d = b, cosa che però non possiamo fare a causa della visibilità (o scope). Il passaggio dei parametri in C avviene sempre per valore, quindi si lavora sempre su una copia del parametro attuale (vedremo in seguito come superare questo limite) e tale caratteristica rende impossibile (almeno al momento) modificare il valore del parametro attuale. Se pensate di superare tale limite usando variabili globali non fatelo. E’ buona norma limitare il più possibile l’uso di tali variabili - la cui visibilità si estende in tutto il file sorgente - e procedere invece ad usare in maniera corretta il meccanismo del passaggio dei parametri.

Per capire meglio il concetto di visibilità prova ad eseguire il seguente codice:

#include <stdio.h>
void swap(int , int); //funzione che scambia il contenuto di due variabili
int main() {
  int x=0,y=1;

  printf("\nBefore the call, x is %d and y is %d",x,y);
  swap(x, y);
  printf("\nAfter the call, x is %d and y is %d\n",x,y);
}

void swap(int x, int y) {
  int tmp;
  tmp=x;
  x=y;
  y=tmp;
}

Come puoi sperimentare, la funzione swap, che dovrebbe scambiare il valore contenuto nelle variabili x e y, non ha invece nessun effetto su queste.

Al momento questo è tutto ciò che ti serve sapere per realizzare ed utilizzare delle nuove funzioni. Successivamente, dopo aver introdotto i puntatori, vedremo come utilizzarle in situazioni più interessanti.