praticamente la funzione scambia i puntatori e i valori... il difficile è capire quando le modifiche sono al valore puntato dal puntatore, o alla cella del puntatore stesso quando ad esempio il puntatore punta ad un altra cella.

Ecco una spiegazione in pseudo-codice:

codice:
il valore puntato da 'b' avrà il valore puntato da 'c'
'b' punterà ad 'a'
il valore puntato da 'c' avrà il valore puntato da 'b'
il valore di 'a' sarà quello puntato da 'c'
ritorna il valore di 'a'
Tenendo conto che SOLO le variabili passate per riferimento come 'b' e 'c' possono subire cabiamenti il valore di 'a' rimarrà 1, visto che lui è per valore; ed ecco il motivo del primo uno ritornato.

Il 3 viene passato a 'c', ma come si vede nel code a 'b' verrà assegnato il valore di 'c', poi 'b' va fatto puntare ad 'a' ed assumerà il valore 1. Poi a 'c' si assegna b, ed ecco l'altro uno. Infine la funzione ritorna il valore di 'a', che sarà sempre 1 visto che è per valore.

La prima volta non è semplice capire queste cose e anche i più esperti fanno avvolte errori di questo genere con puntatori nulli, che escono dall'indice e modificano altra memoria ecc... questi problemi, e la gestione della memoria collegata ad essi, sono tipici della programmazione C.

Diciamo che la chiave per capire tutto è:

codice:
------                   -----------
Puntatore   ----->       valore
-------                  ------------
se dichiari

codice:
int valore = 5;
int* puntatore = &a;
per riferirti alla cella di memoria del puntatore scrivi solo puntatore, per riferirti alla cella cui punta devi dereferenziarlo con *, quindi *puntatore.

Queste cose si capisco con pratica, pratica, pratica e... l'altra che non me la ricordo.