Programmazione · 14 min read · Oct 09, 2025

Imparare C/C++ Passo Dopo Passo - Pagina 6

06. Passo Dopo Passo C/C++ — Programmazione C - Funzioni

Funzioni

I. Introduzione
II. Definizione della funzione
III. Tipi di funzioni
IV. Funzioni integrate

| | 1. Funzioni numeriche

  1. Funzioni stringa
  2. Funzioni di test dei caratteri | | | V. Funzioni definite dall’utente | | | 1. Funzioni semplici
  3. Funzione con argomenti
  4. Funzione con ritorni
  5. Funzione con ricorsione | | | VI. Puntatori e Funzioni | | | 1. Passaggio dei parametri per riferimento
  6. Chiamata per valore
  7. Chiamata per riferimento | | | VII. Locale Vs Globale | | | VIII. Specificatori di classe di archiviazione | | | Classe di archiviazione automatica
    Classe di archiviazione registrata
    Classe di archiviazione statica
    Classe di archiviazione esterna |

I. Introduzione

Ecco un programma per stampare l’indirizzo di una persona due volte, scritto in entrambi i metodi utilizzando funzioni e senza utilizzare funzioni. Dimostrerà il vantaggio delle funzioni.

| | #include
int main()
{
printf(“\nNome della Persona”);
printf(“\nVia, Appartamento//Numero Civico “);
printf(“\nCAP, Città”);
printf(“\nPaese”);

printf(“\nNome della Persona”);
printf(“\nVia, Appartamento//Numero Civico “);
printf(“\nCAP, Città”);
printf(“\nPaese”);

return 0;
} | #include
void address()
{
printf(“\nNome della Persona”);
printf(“\nVia, Appartamento//Numero Civico “);
printf(“\nCAP, Città”);
printf(“\nPaese”);
}

int main()
{
address();
address();

return 0;
} |

II. Definizione della Funzione

Un blocco di istruzioni, che ha la capacità di accettare valori come argomenti e restituire risultati al programma chiamante. Quindi, una funzione è un blocco di istruzioni autonomo che esegue un compito specifico.

III. Tipi di funzioni

| | - Funzioni integrate/ Funzioni di Libreria/ Funzioni Pre-Definite

  • Funzioni definite dall’utente |

IV. Funzioni di Libreria

Le funzioni di libreria sono progettate dal produttore del software, vengono caricate nel disco ogni volta che il software viene caricato.

Le seguenti funzioni sono un esempio delle funzioni di libreria.

1. Funzioni Numeriche

FunzioneSintassiEs.Risultato
AssolutoAbs(n)abs(-35)35
ceilceil(n)ceil(45.232)46
floorfloor(n)floor(45.232)45
fmodfmod(n,m)fmod(5,2)1
coscos(n)cos(60)0.5
sinsin(n)sin(60)0.866
tantan(n)tan(60)1.732
sqrtsqrt(n)sqrt(25)5
powpow(n,m)pow(2,3)8

2. Funzioni Stringa

FunzioniSintassiEs.
strlenstrlen(str)strlen(“Computer”)
strcpystrcpy(target,source)strcpy(res,”Pass”)
strcatstrcat(target,source)strcat(“mag”,”gic”)
strcmpstrcmp(str1,str2)strcmp(“abc”,”Abc”)
strrevstrrev(target,scr)fstrrev(res,”LIRIL”)

3. Funzioni di Test dei Caratteri

FunzioneDescrizione
isalnumè una lettera o cifra
isalphaè una lettera
isdigitè una cifra
iscntrlè un carattere di controllo ordinario
isasciiè un carattere ASCII valido
islowerè un carattere minuscolo
isupperè un carattere maiuscolo
isspaceè un carattere di spazio
isxdigitè un carattere esadecimale

C’è una vasta libreria di funzioni disponibili, ti ho dato solo una piccola parte di essa. Per ulteriori funzioni di libreria, consulta il Manuale di Aiuto.

V. Funzioni Definite dall’Utente

I programmi che hai già visto eseguono divisioni di lavoro. Quando chiami gets, puts, o strcmp, non devi preoccuparti di come funzionano gli interni di queste funzioni.

Queste e circa 400 altre funzioni sono già definite e compilate per te nella libreria Turbo C. Per usarle, devi solo includere il file di intestazione appropriato nel tuo programma, “La libreria di runtime,” nella riferimento della libreria per assicurarti di capire come chiamare le funzioni e quale valore (se presente) restituiscono.

Ma dovrai scrivere le tue funzioni. Per farlo, devi suddividere il tuo codice in sezioni discrete (funzioni) che ciascuna esegue un singolo compito comprensibile per le tue funzioni, puoi chiamarle in tutto il tuo programma nello stesso modo in cui chiami le funzioni della libreria C.

Passi per implementare una funzione

| | 1. Dichiarazione

  1. Chiamata della Funzione
  2. Definizione |

| | • Ogni funzione deve essere dichiarata all’inizio del programma.
• La definizione della funzione contiene il codice effettivo dell’attività di esecuzione.
• Se una funzione è definita all’inizio del programma, non è necessaria la dichiarazione della funzione. |

Un esempio di funzione per dimostrare l’implementazione

| | / 32_egfun.c /
#include

void address(); / Dichiarazione /

int main()
{
address(); / Chiamata della Funzione /
address(); / Chiamata della Funzione /

return 0;
}

void address() / Definizione /
{
printf(“\nNome della Persona”);
printf(“\nVia, Appartamento//Numero Civico “);
printf(“\nCAP, Città”);
printf(“\nPaese”);
} |

Le funzioni definite dall’utente possono essere suddivise in 4 tipi in base a come le chiamiamo.

| | 1. Funzioni Semplici

  1. Funzione con Argomenti
  2. Funzione con Ritorni
  3. Funzione con Ricorsione |

1. Funzioni Semplici

Esegue solo un compito specifico, non è necessario argomenti né valori di ritorno.

Esempio di Funzione Semplice

| | / 33_line.c /
#include
void line(); / Dichiarazione /
int main()
{
line(); / Chiamata della Funzione /
return 0;
}
void line() / Definizione /
{
int i;
for(i =1;i<80; i++)
putch(‘*’);
} |

2. Funzione con Argomenti

Una funzione, che accetta argomenti, è nota come funzione con argomenti.

Es.

| | / 34_argu.c /
void line(char ch, int n)
int main()
{
line(“-“, 50);
line(“*”, 8);
return 0;
}
void line(char ch, int n)
{
int i;
for( i = 1; i<=n; i++ )
putch(ch);
} |

3. Funzione con Valori di Ritorno

Una funzione che può restituire valori al programma chiamante è nota come funzione con valori di ritorno.

Es.

| | / 35_retu.c /
int abs(int n);
int main()
{
int res;
printf(“%d”, abs(-35))

res = abs(-34); / Chiamata della Funzione/

printf(“%d”, res);
return 0;
}
void abs(int n)
{
if( n < 0 )
n = n * -1;
return n;
} |

4. Funzione con Ricorsione

Se un’istruzione all’interno del corpo di una funzione chiama la stessa funzione è chiamata ‘ricorsione’. A volte chiamata ‘definizione circolare’, la ricorsione è quindi il processo di definire qualcosa in termini di se stesso.

Esempi di Funzioni Ricorsive

| | / Il seguente programma dimostra la chiamata della funzione di se stessa /
int main( )
{
printf(“\nCiao”);
main( ); / Una funzione, che può chiamarsi da sola /
return 0;
} Non eseguire questo programma, è ancora una spiegazione quindi il programma non è logicamente valido.

Lo stesso output può essere raggiunto utilizzando un’altra funzione: void disp( );

int main( )
{
disp( );
return 0;
}

void disp( )
{
printf(“\nCiao”);
disp( );
} |

Il programma deve terminare a un certo punto quindi la chiave della ricorsione risiede in un’interruzione morbida, che può essere definita utilizzando un’istruzione condizionale.
Controlla il seguente esempio:

| | / 36_recursion.c /
int i = 1;      / Dichiarazione di una variabile globale /
void disp( );
int main( )
{
disp( );
return 0;
}

void disp( )
{
printf(“\nCiao %d “, i);
i ++;
if( i < 10 ) / se il valore di i è minore di 10 allora chiama di nuovo la funzione /
disp( );
} |

| | Programma per trovare il fattoriale del numero dato:
/ 37_fact.c /
int factorial(int x);
void main
{
int a, fact;
printf(“\nInserisci un numero qualsiasi “); scanf(“%d”, &a);
fact = factorial(a);
printf(“\nIl fattoriale è = %d”, fact);
}
int factorial(int x)
{
int f = 1, i;
for( i = x; i>=1; i–)
f = f i;
return f;
} | Per trovare il fattoriale di un numero dato utilizzando la ricorsione
/
38_fact.c /
int rec_fact(int x);
int main( )
{
int a, fact;
printf(“\nInserisci un numero qualsiasi “); canf(“%d”, &a);
fact = rec_fact(a);
printf(“\nIl valore del fattoriale è = %d”, fact);
return 0;
}
int f = 1;
int rec_fact(int x)
{
if( x > 1)
f = x
rec_fact(x-1);
return f;
} |

VI. Puntatori e Funzioni

| | Passaggio dei Parametri per Riferimento
Chiamata per valore
Chiamata per Riferimento
|

1. Passaggio dei Parametri per Riferimento

Il puntatore può essere utilizzato nella dichiarazione della funzione e questo rende una funzione complessa facilmente rappresentabile e accessibile. La definizione della funzione utilizza i puntatori in essa, in due modi

| | – Chiamata per valore

  • Chiamata per riferimento |

Il meccanismo di chiamata per riferimento è veloce rispetto al meccanismo di chiamata per valore perché nella chiamata per riferimento, viene passato l’indirizzo e la manipolazione con gli indirizzi è più veloce rispetto alle variabili ordinarie. Inoltre, viene creata solo una posizione di memoria per ciascun parametro effettivo.

Quando una porzione del programma, gli argomenti effettivi, chiama una funzione e i valori alterati all’interno della funzione verranno restituiti alla porzione chiamante del programma in forma alterata. Questo è chiamato chiamata per riferimento o chiamata per indirizzo. L’uso del puntatore come argomento della funzione in questo meccanismo consente agli oggetti dati di essere alterati globalmente, cioè all’interno della funzione e all’interno della porzione chiamante del programma. Quando un puntatore viene passato alla funzione, viene passato l’indirizzo dell’argomento alle funzioni e i contenuti di questo indirizzo vengono accessibili globalmente. Le modifiche apportate ai parametri formali (parametri utilizzati nella funzione) influenzano il valore originale dei parametri effettivi (parametri utilizzati nella chiamata della funzione nel programma chiamante).

Es.

| | / 39_func.c /

void func_c( int *x );

int main()
{
int i = 100;
int *a;
a = &i;
printf(“\nIl valore è %d”, i);
func_c(a);
printf(“\nIl valore è %d”, i);
return 0;
}

void func_c( int x )
{
(
x) ++;
printf(“\nIl valore nella funzione è %d “, *x);
} |

Nel programma sopra, ci sono totalmente tre dichiarazioni ‘printf’, due nella funzione main() e una nella sottoprogramma della funzione. A causa dell’effetto della prima dichiarazione printf, il valore di i viene stampato come 100. Successivamente viene effettuata la chiamata alla funzione e all’interno della funzione, il valore viene alterato e diventa 101 a causa dell’incremento. Il valore alterato viene nuovamente restituito a main() e viene stampato come 101.

Quindi l’output è:

| | Il valore è 100
Il valore nella funzione è 101
Il valore è 101 |

Di più sulle Chiamate di Funzione

Avendo avuto il primo incontro con i puntatori, torniamo ora a ciò che ci eravamo originariamente proposti di imparare: i due tipi di chiamate di funzioni: chiamata per valore e chiamata per riferimento. Gli argomenti possono generalmente essere passati alla funzione in uno dei due modi:

| | a. Inviando i valori degli argomenti
b. Inviando gli indirizzi degli argomenti |

2. Chiamata per Valore

Nel primo metodo, il ‘valore’ di ciascuno degli argomenti effettivi nella funzione chiamante viene copiato nei corrispondenti argomenti formali della funzione chiamata. Con questo metodo, le modifiche apportate agli argomenti formali nella funzione chiamata non hanno effetto sui valori degli argomenti effettivi nella funzione chiamante. Il seguente programma illustra la Chiamata per Valore.

| | / 40_callbyvalue.c /
void swap( int x, int y )
int main( )
{
int a = 10, b = 20;
swap( a ,b );
printf(“\n a = %d, b = %d “, a, b);
return 0;
}
void swap( int x, int y )
{
int t;
t = x;
x = y;
y = t;
printf(“\nx = %d, y = %d”, x, y);
} |

L’output del programma sopra sarebbe:

| | x = 20 y = 10
A = 10 b = 20 |

Nota che i valori di a e b rimangono invariati dopo lo scambio dei valori di x e y.

3. Chiamata per Riferimento

Questa volta gli indirizzi degli argomenti effettivi nella funzione chiamante vengono copiati negli argomenti formali della funzione chiamata. Questo significa che utilizzando questi indirizzi avremmo accesso agli argomenti effettivi e quindi saremmo in grado di manipolarli. Il seguente programma illustra questo fatto.

| | 41_callbyref.c /

void swap( int x, int y )

int main()
{
int a = 10, b = 20;
swap( &a, &b);
printf(“\na = %d, b = %d”, a, b);
return 0;
}

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

L’output del programma sopra sarebbe:

| | A = 20, b = 10 |

Nota che questo programma riesce a scambiare i valori di a e b utilizzando i loro indirizzi memorizzati in x e y. Di solito nella programmazione C facciamo una chiamata per valore. Cioè, in generale non puoi alterare gli argomenti effettivi. Ma se desiderato, può sempre essere raggiunto tramite una chiamata per riferimento.

Utilizzando la chiamata per riferimento in modo intelligente

possiamo creare una funzione, che può restituire più di un valore alla volta, cosa che non è possibile ordinariamente. Questo è mostrato nel programma qui sotto.

| | / 42_callbyref.c /

void areaperi(int r, float a, float p)

int main()
{
int radius;
float area, perimeter;
printf(“\nInserisci il raggio di un cerchio :”); scanf(“%d”, &radius);

areaperi(radius, &area, &perimeter);

printf(“\nArea = %f “, area);
printf(“\nPerimetro = %f”, perimeter);
return 0;
}

void areaperi(int r, float a, float p)
{
a = 3.14 r r; p = 2 3.14 r;
} |

E qui c’è l’output:

| | Inserisci il raggio di un cerchio 5
Area = 78.500000
Perimetro = 31.400000 |

Qui, stiamo facendo una chiamata mista, nel senso che stiamo passando il valore di radius ma, l’indirizzo di area e perimetro. E poiché stiamo passando gli indirizzi, qualsiasi cambiamento che facciamo nei valori memorizzati negli indirizzi contenuti nelle variabili a e p, renderebbe il cambiamento efficace in main. Ecco perché quando il controllo ritorna dalla funzione areaperi( ) siamo in grado di stampare i valori di area e perimetro.
Così, siamo stati in grado di restituire due valori da una funzione chiamata, e quindi, abbiamo superato la limitazione della dichiarazione return, che può restituire solo un valore da una funzione alla volta.

VII. Variabili Locali Vs Globali

Secondo l’ambito degli identificatori, le variabili sono dichiarate come tipi.

| | / 42_globalid.c /
int i=4000; / Dichiarazione di variabile globale/
int main()
{
int a=10, b=20; / Variabile Locale /
int i=100; / Variabile Locale /
printf(“%d %d”, a, b);
printf(“\nVariabile locale i : %d”, i); / Accesso alla variabile Locale /
printf(“\nVariabile globale i : %d “, ::i); / Accesso alla variabile Globale /
return 0;
} |

Nota: L’operatore di risoluzione dell’ambito ( :: ) può essere disponibile solo in C++.

VIII. Specificatori di Classe di Archiviazione

Fino a questo punto, siamo già familiari con la dichiarazione delle variabili. Per definire completamente una variabile, è necessario menzionare non solo il suo ‘tipo’ ma anche la sua ‘Classe di Archiviazione‘.
Secondo questa sezione, le variabili non solo hanno un ‘tipo di dato’, ma hanno anche una ‘Classe di Archiviazione’.

Le Classi di Archiviazione sono di 4 Tipi

| | 1. Classe di Archiviazione Automatica

  1. Classe di Archiviazione Registrata
  2. Classe di Archiviazione Statica
  3. Classe di Archiviazione Esterna |

1. Classe di Archiviazione Automatica

Parola Chiaveauto
ArchiviazioneMemoria
Valore PredefinitoNull
AmbitoLocale al blocco in cui è definita la variabile
VitaFino all’esecuzione del suo blocco

Es:

| | / 43_auto.c /
#include
int main()
{
auto int i, j;
printf(“%d %d”, i, u);
return 0;
} |

2. Classe di Archiviazione Registrata

Parola Chiaveregister
ArchiviazioneRegistri CPU
Valore PredefinitoNull
AmbitoLocale al blocco in cui è definita la variabile
VitaFino all’esecuzione del suo blocco

Es:

| | / 44_register.c /
#include
int main( )
{
register int i, j;
for(i=1;i<=10;i++)
printf(“\n%d”, i);
return 0;
} |

3. Classe di Archiviazione Statica

Parola Chiavestatic
ArchiviazioneMemoria
Valore PredefinitoZero
AmbitoLocale al blocco in cui è definita la variabile
VitaIl valore della variabile persiste tra diverse chiamate di funzione

Es:

| | / 45_static.c /
#include
void add();
int main()
{
add();
add();
add();
return 0;
}
void add()
{
static int i = 1;
printf(“%d\n”,i++);
} |

4. Classe di Archiviazione Esterna

Parola Chiaveextern
ArchiviazioneMemoria
Valore PredefinitoZero
AmbitoGlobale
VitaFinché l’esecuzione del programma non termina

Es:

| | / 46_extern.c /
#include
int i;
void add(); / Variabile Extern /
int main( )
{
extern j=10; / Variabile Extern /
for(i=1;i<=10;i++)
add();
return 0;
}
void add( )
{
j++;
printf(“%d %d\n”, i, j);
} |

Share: X/Twitter LinkedIn

Ricevi i nuovi post nella tua casella di posta.

Nessuno spam. Disiscriviti in qualsiasi momento.