Problema
Scrivere una funzione di tipo main
che richiami una funzione di tipo int
denominata pot_ennesima
che calcoli la potenza n-ma di assegnato numero intero.
Struttura di una funzione
Di seguito si riporta la specifica della funzione che si vuole costruire. Si osservi che prima di iniziare il main
la funzione viene dichiarata secondo le proprie caratteristiche strutturale. Ovvero “in gergo” diremo che abbiamo scritto il prototipo della funzione.
int pot_ennesima(int base, int n)
int
è il tipo del valore che la funzione deve ritornare;pot_ennesima
è il nome della funzione ed memorizza il valore di ritorno;int base
, int n
rappresentano i parametri di ingresso, ovvero i valori di input, passati alla funzione. In questo esempio abbiamo due parametri interi in input.La funzione
Un funzione viene richiamata attraverso una istruzione del tipo:
potenza = pot_ennesima(2,i);
nel programma di tipo main
. L’inzio e la fine della funzione sono individuati dalla apertura e dalla chiusura di parentesi graffe:
int pot_ennesima(int base, int n){
...
return p;
}
L’istruzione return p
restituisce in output alla funzione chiamante main()
il valore di output p attraverso il nome della funzione.
N.B. Si osservi che se la funzione è di fissato tipo (ad esempio int) il valore ritornato (quello a fianco a return) deve essere dello stesso tipo (nel nostro caso int).
Problema
Scrivere una funzione di tipo main
che richiami una funzione di tipo int
denominata scambio
che scambi il valore di due variabili di tipo float.
Passaggio di parametri ad una funzione
Se si prova ad eseguire il precedente codice avviene che programma non dà il risultato atteso. Si ottiene infatti:
a=3 b=5
Quello che avviene è mostrato in figura.
Ovvero:
In C il passaggio dei parametri avviene per valore non per indirizzo di memoria.
Passaggio di parametri ad una funzione
In C il passaggio dei parametri avviene per valore non per indirizzo di memoria.
I Puntatori:
Nel linguaggio C esistono della “variabili speciali”, dette puntatori, che contengono l’indirizzi di memoria.
Nell’esempio in figura si vede che la variabile p contiene l’indirizzo in memoria della variabile x. Potremo dire che p è una variabile che memorizza il numero civico dell’abitazione di x.
In generale, si dice che p punta ad x o anche che p è un puntatore per x.
p è un puntatore alla variabile x, ovvero p è una variabile che contiene l’indirizzo della variabile x.
L’istruzione
p = &x;
assegna l’indirizzo di x (nell’esempio 10001) alla variabile puntatore p da questo momento p punta a x.
Per conoscere il valore della variabile puntata da p ( nell’esempio il valore di x che è 5 ) si utilizza l’operatore unario *
. In particolare:
*p
è il contenuto dell’area di memoria puntata da p, cioè nel nostro esempio *p vale 5 ossia il valore della variabile x.
Una variabile puntatore deve essere dichiarata necessariamente allo scopo a cui è adibita.
Ad esempio se si dichiara all’inizio di una funzione:
int *p;
p è una variabile puntatore ad una locazione di memoria di tipo intero.
Esempio:
Vediamo con qualche esempio come sia possibile manipolare dei puntatori:
int x=1, y=2, z[10];
int *p; /* dichiarazione del puntatore p */
p = &x; /* p ora punta a x */
y = *p; /* y ora vale 1 */
*p = 0; /* x ora vale 0 */
p = &z[0]; /* p ora punta a z[0] */
Nell’esempio p è un puntatore utilizzato al punto 3 per individuare la variabile x e al punto 6 per puntare alla variabile z[0].
I puntatori possono apparire nelle espressioni, ad esempio:
int x,y, *p;
p=&x;
y = *p +1; /* equivale a y = x+1; */
*p += 1; /* equivale a x = x+1; */
*p = 10; /* equivale a x=10; */
Se q è un altro puntatore ad una variabile intera, l’istruzione
q = p;
copia il contenuto di p in q. In base a quanto detto questo significa che q punta alla stessa variabile a cui punta p.
Problema
Scrivere una funzione di tipo main
che richiami una funzione di tipo int
denominata scambio
che scambi il valore due variabili di tipo float.
Passaggio di parametri ad una funzione per indirizzo
Se si prova ad eseguire il precedente codice con la chiamata:
scambio(&a, &b)
gli indirizzi delle variabili a e b vengono “copiati” nelle variabili px e py.
i puntatori px e py scambiano il loro valore ovvero gli indirizzi che contengono
la funzione ritorna il controllo al main.
In C il passaggio dei parametri per indirizzo si ottiene utilizzando nella chiamata l’operatore &.
Array
Esiste una stretta correlazione tra array e puntatori. Con l’istruzione:
int a[10], *pa;
Viene allocato un vettore di interi di lunghezza 10 ed un puntatore ad intero. Per puntare all’array è sufficiente l’istruzione:
pa = &a[0];
E’ possibile accedere agli elementi del vettore a attraverso il puntatore pa. Inoltre:
Array
Per definizione il nome di un array è l’indirizzo del primo elemento dell’array, per cui nell’esempio il nome:
a
rappresenta l’indirizzo del vettore a[10], è dunque esso stesso un puntatore. Riportiamo alcuni esempi di utilizzo di array e puntatore:
Nota
Si deve però tenere presente che:
Secondo tale osservazione si evince che:
pa=a; pa++;
sono istruzioni consentite.
Mentre
a=pa; a++;
non sono delle istruzioni consentite.
Passaggio di un array ad una funzione
Se il nome di un array è passato come argomento ad una funzione, in realtà è passato l’indirizzo del primo elemento dell’array. Per cui ad esempio si può ragionare nella seguente maniera:
main()
{
int a[3];
...
fun(a);
...
}
Il prototipo della funzione può essere strutturato in uno dei seguenti modi:
1. Prolusione
2. Sistemi Operativi – parte prima
3. Sistemi Operativi – parte seconda
6. Il linguaggio C – parte prima
8. Il linguaggio C – funzioni e puntatori
10. Il linguaggio C – parte terza
11. La documentazione del software
12. Dati strutturati
13. Esercizi sui dati strutturati
14. Approfondimenti di C, Stringhe e file
15. Esercizi su stringhe e file
16. La ricorsione
17. Il linguaggio c++ parte prima
18. Il linguaggio C++ - parte seconda
19. Strutture dati di tipo astratto