Mi sa che io erroneamente ragiono in termini di variabili, ma qui si ha a che fare con funzioni e la cosa funziona diversamente
Il problema è che finora hai usato i puntatori ma realmente non hai capito cosa sono,un puntatore classico e uno a funzione lavorano grosso modo nella stessa maniera.
Proviamo a chiarire il concetto e per fare ciò ci inventiamo un fantacomputer,questo fantacomputer avrà una fantacpu e una fantamemoria.
La memoria sarà come un enorme vettore in base 0,avremo quindi:
MEM[0] == prima cella di memoria
MEM[LAST] == ultima cella di memoria
La fantacpu invece eseguirà dei comandi contenuti nella memoria stessa,partendo esattamente dalla cella 0 della memoria leggerà ed eseguirà il comando.
Il primo problema è dove posizionare le variabili,dato lo scorrimento verso il basso della cpu sulla memoria potrebbero esserci collisioni,allora noi mettiamo le variabili a partire dal fondo della memoria.
Quindi se noi scrivessimo in c questa riga:
il nostro fantacompilatore farà:
ricordandosi che la variabile A è contenuta nell'offset LAST
ma se noi adesso scriviamo
Il nostro fanta compilatore farà:
Codice: Seleziona tutto
//LAST == offset A
//LAST-1 == offset B;
MEM[LAST-1] = LAST;
Salvando dentro la cella indirizzata da B l'offset della cella A.
Ora se noi scriviamo:
Il nostro amicone farà:
Codice: Seleziona tutto
//CURRENT = 0 == Offset codice in memoria
//LAST == offset A
//LAST-1 == offset B;
//LAST-2 == offset C;
MEM[LAST] = 10; // int a = 10;
MEM[LAST-1] = LAST; // int* b = &a;
MEM[CURRENT++] ={ MEM[LAST-2] = ADDIZIONA( MEM[LAST], MEM[MEM[LAST-1]]) }; // c = a + *b;
Analizziamo l'ultima riga:
Inanzitutto Salviamo nella cella "MEM[CURRENT]"(current parte da 0 dato che la fcpu parte ad eseguire il codice da 0) l'operazione che vogliamo eseguire.
L'operazione è racchiusa tra le graffe.
Nel nostro caso memorizzo che devo fare un'addizione tra due celle di memoria e salvare il risultato nella cella LAST-2 che sarà l'offset di c.
Nel primo parametro il fantacompilatore passa direttamente il contenuto della cella di memoria tramite "MEM[LAST]",nel secondo caso invece gli abbiamo detto che il valore nella cella è un puntatore tramite * e quindi il fantacompilatore andrà ad accedere a tale memoria.
Ottenendo cosi:
MEM[MEM[LAST-1]] -> MEM[last] -> 10
Se non avremmo scritto l'asterisco allora il fantacompilatore avrebbe scritto la riga cosi:
Codice: Seleziona tutto
MEM[CURRENT++] ={ MEM[LAST-2] = ADDIZIONA( MEM[LAST], MEM[LAST-1]) }; // c = a + b;
ottenendo per il secondo parametro un valore di:
MEM[LAST-1] -> LAST
Mettiamo il caso che LAST valga mille e quindi abbiamo 1000 celle di memoria avremmo ottenuto un'addizione di 10+1000 e non 10+10.
Ecco spiegato il concetto di puntatore.
Ora noi possiamo creare tanti puntatori quanti ne vogliamo es:
Codice: Seleziona tutto
int A = 10;
int* B = &A;
int** C = &B;
int*** D = &C;
int**** E = &D;
Codice: Seleziona tutto
//LAST == offset A
//LAST-1 == offset B;
//LAST-2 == offset C;
//LAST-3 == offset D;
//LAST-4 == offset E;
MEM[LAST] = 10; // int a = 10;
MEM[LAST-1] = LAST; // int* b = &a;
MEM[LAST-2] = LAST - 1; // int** c = &b;
MEM[LAST-3] = LAST - 2; // int*** d = &c;
MEM[LAST-4] = LAST - 3; // int**** e = &d;
Se volessimo il valore puntato da "E" ovvero (A==10) dovremmo fare:
come vedi il meccanismo rimane identico.
Per i puntatori a funzione avviene la stessa identica cosa ma un pelo diversa.
Come già detto la nostra cpu esegue i comandi contenuti in memoria e nel nostro semplice esempio nella cella MEM[0] ci abbiamo messo un'addizione.Appena partirà la cpu eseguirà direttamente quel comando e proseguirà con i sucessivi comandi.
Ora mettiamo il caso che la cpu possa eseguire il comando SALTA, questo comando gli fa continuare il lavoro in un'altra area della memoria,potremmo quindi ad esempio memorizzare nella cella MEM[500] una funzione che ne so Pippo().
Il codice:
Codice: Seleziona tutto
void Pippo(void)
{
++c;
}
int a = 10;
int* b = &a;
int c = a + *b;
Pippo();
Codice: Seleziona tutto
//CURRENT = 0 == Offset codice in memoria
//LAST == offset A
//LAST-1 == offset B;
//LAST-2 == offset C;
//Pippo == 500
MEM[LAST] = 10; // int a = 10;
MEM[LAST-1] = LAST; // int* b = &a;
MEM[CURRENT++] ={ MEM[LAST-2] = ADDIZIONA( MEM[LAST], MEM[MEM[LAST-1]]) }; // c = a + *b;
MEM[CURRENT++] ={ SALTA(500) }; //Pippo()
MEM[500] = { MEM[LAST-2] = ADDIZIONA( MEM[LAST-2] , 1) ; // void Pippo(void){ ++c;}
Quindi dopo la prima addizione mettiamo il comando SALTA alla cella 500 che conterrà la nostra funzione che somma 1 a C.
Ora ecco cosa succede se noi mettiamo un puntatore a funzione sul nostro fantacomputer
Codice: Seleziona tutto
void Pippo(void)
{
++c;
}
int a = 10;
int* b = &a;
int c = a + *b;
void(*PIPPO)(void) = Pippo;
PIPPO();
Codice: Seleziona tutto
//CURRENT = 0 == Offset codice in memoria
//LAST == offset A
//LAST-1 == offset B;
//LAST-2 == offset C;
//LAST-3 == offset puntatore a funzione PIPPO
//Pippo == 500
MEM[LAST] = 10; // int a = 10;
MEM[LAST-1] = LAST; // int* b = &a;
MEM[CURRENT++] ={ MEM[LAST-2] = ADDIZIONA( MEM[LAST], MEM[MEM[LAST-1]]) }; // c = a + *b;
MEM[LAST-3] = 500; // void(*PIPPO)(void) = Pippo;
MEM[CURRENT++] ={ SALTA(MEM[LAST-3]) }; //PIPPO()
MEM[500] = { MEM[LAST-2] = ADDIZIONA( MEM[LAST-2] , 1) ; // void Pippo(void){ ++c;}
Come vedi in questo caso invece di mettere il valore dell'offset della cella di Pippo ci mettiamo un'area della memoria che punta a quell'indirizzo.In questo modo quando il comando legge la cella LAST-3 leggerà 500 ovvero l'offset di Pippo.
Come vedi funziona alla stessa maniera dei puntatori normali.
Col nostro fantacomputer avremmo potuto fare anche
Codice: Seleziona tutto
MEM[LAST-4] = 500;
MEM[LAST-3] = MEM[LAST-4];
MEM[CURRENT++] = { SALTA(MEM[LAST-3]) }
Usiamo dunque un puntatore a funzione quando vogliamo saltare all'interno della cella a cui punta la variabile PIPPO, ma non possiamo usare direttamente il puntatore void* fp perchè altrimenti il compilatore non saprebbe come comportarsi.
Ora quindi il discorso di * ** *** **** ***** è identico al codice spiegato con le variabili,solo che sarà inserito all'interno di SALTA. tutto qui.
Se sei riuscito a capire questo fantacomputer allora sei molto vicino a capire come lavora realmente un microprocessore e la sua ram.
Solo che in questo caso una realecpu = fantacpu * difficoltà ^ 1000; tutto qui.