Non mi è molto chiaro ciò che intendi... ma provo con un altra spiegazione.
La cosa è un po' contorta e dovrebbe essere analizzata in un altro modo, ad un livello più basso.
Quando chiami una funzione vengono passati i parametro, in questo caso viene sfruttato lo stack.
Prendiamo il mio codice:
Output, giusto per avere le idee più chiare in seguito:codice:using namespace std; #include <iostream> void cambia(int m,int n[2], int l, int g){ int i; for(i=0;i<5;i++) cout << "n["<<i<<"]: " << n[i] <<endl; cout << "Indirizzo n "<< n<<endl; cout << "indirizzo m "<< &m<<endl; cout << "Indirizzo l "<< &l<<endl; cout << "Indirizzo g "<< &g<<endl; cout << "Indirizzo i "<< &i<<endl; } int main(){ int vet[] ={1,2,3,4,5}; cambia(vet[4],vet-5, 10,100); cout << "\nIndirizzo vet: "<<vet; return 0; }
codice:n[0]: 10 n[1]: 100 n[2]: 1991806165 n[3]: -885658597 n[4]: -2 Indirizzo n 0x28fee8 indirizzo m 0x28fee0 Indirizzo l 0x28fee8 Indirizzo g 0x28feec Indirizzo i 0x28fecc Indirizzo vet: 0x28fefc
A basso livello accade questo:
Non so se conosci assembly, ma per non prendere il giro troppo alla larga diciamo che la prima istruzione che vedi, con [ESP+2C] sta accedendo alla posizione vet[4] dell'array e quindi salva il contenuto in EAX (fai caso al fatto che ESP+2C è l'ultimo elemento, il primo quindi si trova a [ESP+1C], visto che sono ogni 4byte).codice:MOV EAX,DWORD PTR SS:[ESP+2C] MOV DWORD PTR SS:[ESP+C],64 MOV DWORD PTR SS:[ESP+8],0A LEA EDX,DWORD PTR SS:[ESP+1C] SUB EDX,14 MOV DWORD PTR SS:[ESP+4],EDX MOV DWORD PTR SS:[ESP],EAX CALL asd.0040138C
Successivamente mette in ESP+C il valore 64 (che in decimale è il numero 100).
Poi inserisce in EAX+8 l'elemento 0A.
Poi come vedi accede a ESP+1C (primo elemento dell'array) ed in pratica prende tale indirizzo.
Nell'istruzione successiva effettua un SUB, che è una sottrazione in pratica fa quindi EDX = EDX - 14. Il numero 14 è espresso in esadecimale, ed in decimale corrisponde al 20. Non è un caso, in quanto l'array lo passiamo come vet-5 (5 elementi da 4 byte ciascuno = 20byte).
Le ultime tre istruzioni indicano appunto ESP+4 (indirizzo del primo elemento dell'array, 10, a cui viene assegnato l'indirizzo modificato poco sopra grazie alla sottrazione) ed il primo parametro che passi alla funzione, ovvero l'elemento dell'array preso precedentemente, ovvero 5.
La successiva è la chiamata alla funzione cambia().
Ora qui non lo puoi vedere, ma nello Stack dove sono presenti i parametri i dati sono i seguenti:
La colonna a sinistra indica gli indirizzi di memoria, quella a destra indica i dati contenuti.codice:0028FEE8 |0000000A 0028FEEC |00000064 0028FEF0 |76B88CD5 msvcrt.76B88CD5 0028FEF4 |B346661C 0028FEF8 |FFFFFFFE 0028FEFC |00000001 0028FF00 |00000002 0028FF04 |00000003 0028FF08 |00000004 0028FF0C |00000005
ESP+1C puntava prima della sottrazione all'indirizzo 28FEFC. Se vai a vedere sull'Output vedi che questo è in effetti l'indirizzo di vet.
Dopo alla sottrazione quindi, vado indietro di 20byte (5 posizioni), e mi ritrovo all'indirizzo: 0028FEE8 che "casualmente" (l'ho fatto ovviamente apposta quando ho passato parametri ed array) contiene il valore 0A (10, in decimale; è il parametro della funzione passato dopo a vet-5).
I primi due valori stampati sono quindi 10 e poi 100 (64 in esadecimale). Come vedi l'output successivo è "sporco" come dici tu.
Renditi conto che se prendi il mio codice e lo esegui più volte vedrai che i valori "sporchi" non sono sempre uguali (guarda la posizione [3]).
Altri due Output:
Output:codice:n[0]: 10 n[1]: 100 n[2]: 1991806165 n[3]: 470907442 n[4]: -2 Indirizzo n 0x28fee8 indirizzo m 0x28fee0 Indirizzo l 0x28fee8 Indirizzo g 0x28feec Indirizzo i 0x28fecc
Se passo come parametro vet-1 al posto del valore precedente, come output ottengo:codice:n[0]: 10 n[1]: 100 n[2]: 1991806165 n[3]: 1217724272 n[4]: -2 Indirizzo n 0x28fee8 indirizzo m 0x28fee0 Indirizzo l 0x28fee8 Indirizzo g 0x28feec Indirizzo i 0x28fecc
E come vedi tutto torna: il valore -2 era presente anche prima, ma nella quinta posizione dell'array.codice:n[0]: -2 n[1]: 1 n[2]: 2 n[3]: 3 n[4]: 4 Indirizzo n 0x28fef8 indirizzo m 0x28fee0 Indirizzo l 0x28fee8 Indirizzo g 0x28feec Indirizzo i 0x28fecc
Ometto il codice relativo alla funzione cambia() in quanto il ciclo non è di facile ed immediata comprensione, visto così; effettua comunque le operazioni utilizzando ESP come visto sopra.
PS: ho usato MinGw come compilatore.
Compila il mio codice e vedi che cosa ottieni. Passami se vuoi il file exe che ottieni.

Rispondi quotando