Dalla A alla Z passando per C - Robotica
Dalla A alla Z passando per C - Robotica
Dalla A alla Z passando per C - Robotica
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
void swap(int *a, int *b)<br />
{<br />
int tmp;<br />
}<br />
tmp = *a;<br />
*a = *b;<br />
*b = tmp;<br />
Gli argomenti delle funzioni possono essere tipi semplici o strutture dati e, come detto, sono<br />
sempre passati <strong>per</strong> valore; anche se è consentito, normalmente non vengono passate strutture<br />
dati né come argomenti né come valori di ritorno. Si preferisce invece, <strong>per</strong> ragioni di efficienza,<br />
allocare le strutture dati separatamente e passare solo i puntatori ad esse, effettuando così un<br />
passaggio <strong>per</strong> riferimento.<br />
Perchè si parla di questioni di efficienza? Come detto, il passaggio dei parametri che avviene<br />
<strong>per</strong> valore comporta l’allocazione di una copia locale delle variabili dichiarate nella lista dei<br />
parametri. Oltre all’allocazione, tali variabili devono anche essere inizializzate <strong>per</strong> riflettere il<br />
valore delle variabili o espressioni del chiamante. Questo comporta, nel caso in cui il parametro<br />
passato sia una variabile, la copia esplicita di una porzione di memoria d<strong>alla</strong> variabile utilizzata<br />
<strong>per</strong> la chiamata <strong>alla</strong> variabile locale. Nel caso le variabili siano strutture dati c’è quindi una<br />
<strong>per</strong>dita di efficienza nel passaggio dei parametri che è proporzionale <strong>alla</strong> dimensione della variabile,<br />
in quanto il tempo necessario <strong>alla</strong> copia del valore aumenta all’aumentare della dimensione<br />
della struttura.<br />
Un altro caso in cui è utilizzato il passaggio <strong>per</strong> riferimento è nel caso in cui una funzione<br />
debba ritornare più di un valore, <strong>per</strong> esempio un numero intero e un codice di errore. Anche<br />
in questo caso è possibile utilizzare il passaggio <strong>per</strong> riferimento e passare quindi dei puntatori<br />
come argomenti ulteriori, in modo che la funzione possa scrivere i valori di ritorno in una o più<br />
variabili del chiamante. Esempio:<br />
int findid(struct obj *item, int *errorptr)<br />
{<br />
if (isvalid(item) == 0) {<br />
*errorptr = ERR_INVALID;<br />
return 0;<br />
}<br />
*errprptr = ERR_NOERROR;<br />
return internal_findid(item);<br />
}<br />
Nell’esempio precedente, la funzione findid viene utilizzata <strong>per</strong> trovare un valore intero all’interno<br />
della struttura passata come argomento (anche la struttura è passata <strong>per</strong> riferimento, <strong>per</strong> i<br />
motivi di efficienza appena illustrati). Quindi il tipo restituito d<strong>alla</strong> funzione findid è intero. Per<br />
ricercare il valore, findid si appoggia <strong>alla</strong> funzione internal_findid, che accetta il puntatore<br />
<strong>alla</strong> struttura come parametro. Prima di chiamare internal_findid, findid effettua dei controlli<br />
di validità sulla struttura, in quanto internal_findid si aspetta in ingresso una struttura<br />
corretta. Inoltre, internal_findid deve notificare al chiamante il fatto di aver ricevuto o meno<br />
una struttura corretta, in modo che il chiamante non interpreti erroneamente il valore di ritorno<br />
di findid. Ecco che il secondo parametro di findid viene modificato internamente <strong>alla</strong> funzione<br />
<strong>per</strong> assegnargli il codice di errore e, di fatto, ritornare un secondo valore di uscita. Un possibile<br />
uso della funzione dell’esempio è il seguente:<br />
98