sabato, novembre 04, 2006

Algebra dei puntatori


#include <stdio.h>
#include <stdlib.h>
#include <new.h>
int main() {


//
//L'ALGEBRA DEI PUNTATORI
//

/*
Una volta allocato array dinamico, per accedere ai singoli elementi allocati
il C++ mette a disposizione delle operazioni algebriche sui puntatori,
capaci di restituire l'indirizzo di memoria di un particolare elemento
a partire dall'indirizzo "di testa" dell'array (quello che viene restituito
dalla funzione new) e da un intero che specifica la posizione ordinale
della cella che si desidera specificare.
*/


float *Pd;
printf(
"\n\n * * * ALGEBRA DEI PUNTATORI * * *\n\n");

Pd =
new float[10]; //alloco 10 float
printf("Indirizzo della locazione di memoria: %p\n",Pd);
*Pd =
355.0/113;
printf(
"Contenuto della locazione a quell'indirizzo: %g\n",*Pd);

//ADDIZIONE: (con interi, non fra puntatori!!!)

printf("Indirizzo immediatamente successivo al primo: %p\n",Pd+1);
*(Pd+
1) = 2* *Pd; //Il secondo float dell'array uguale a due volte il primo
printf("Contenuto della locazione a quell'indirizzo: %g\n",*(Pd+1));

printf(
"Attenzione alle precedenze!\n");
printf(
"*(Pd+1) = %g \nmentre\n*Pd+1 = *(Pd) + 1 = %g\n",*(Pd+1),*Pd+1);

//INCREMENTO - - - A T T E N Z I O N E - - -
printf("\n\n * * * Incremento coi puntatori * * *\n\n");

float *P; //puntatore di appoggio

printf("caso 1\n");
P = Pd;
printf(
"%p\n",P);
P++;
printf(
"%p\n",P); //P ora punta alla seconda locazione a partire da Pd!!!


printf("\ncaso 2\n");
P = Pd;
printf(
"%p\n",P);
printf(
"%p\n",P++); //Prima viene "restituito" il valore di P, poi incrementato!
printf("%p\n",P);

printf(
"\ncaso 3\n");
P = Pd;
printf(
"%p\n",P);
printf(
"%p\n",++P); //Prima viene incrementato il valore di P, poi restituito!
printf("%p\n",P);

printf(
"\nper cui:\n\n");
P = Pd;
printf(
"*P++ = *(P++) = %g = contenuto della PRIMA cella\n",*P++);
printf(
"e successivamente P si ritrova incrementato di uno: %p\n\n",P);
printf(
"MENTRE\n\n");
P = Pd;
printf(
"*++P = *(++P) = %g = contenuto della SECONDA cella\n",*++P);
printf(
"e P resta e' incrementato di uno: %p\n\n",P);


/*
SOTTRAZIONE (fra puntatori!!!)
*/
printf("\n * * * Sottrazione fra puntatori * * *\n\n");
//In teoria...
char *C;
C =
new char[1];
printf(
"C,C+1 = %p %p \n",C,C+1);
float *Q;
Q =
new float[10];
int diff = Q-P; //Distanza (in unita' di float) fra i due indirizzi
printf("diff = %d\n",diff);
printf(
"P C Q = %p %p %p\n",P,C,Q);
delete[] Q;
delete[] C;

//In pratica:
P = Pd+3; //quarto elemento dell'array...
Q = Pd+7; //ottavo elemento dell'array...

diff = Q-P; //distanza fra gli elementi DI UNO STESSO ARRAY!!!
//Infatti non e' possibile fare la differenza fra puntatori
//di "tipo" diverso...

/*
Il modo di gestire gli array allocati dinamicamente tramite l'algebra
sui puntatori, e' in realta' precisamente il modo con cui il C++ stesso
gestisce tutti gli array, anche quelli dichiarati staticamente.
Di fatto, le due sintassi sono esattamente sovrapponibili, con la seguente
equivalenza:
nome_array <--> puntatore al primo elemento dell'array
*/

P[3] = 12.3; //P era un puntatore, ma lo uso come un vettore!
//e' equivalente a:
*(P+3) = 12.3;
//Ecco spiegato perche' negli array gli indici partono da zero e non da 1!!!

int ARRAY[10];
int *pi;
pi = ARRAY;
//ARRAY senza quadre rappresenta l'indirizzo del primo elemento!
pi = ARRAY+5;

*(ARRAY) =
3;
//e' equivalente a:
ARRAY[0] = 3;


//e cosi' via...


/*
Il C++ non consente la creazione DINAMICA di array multidimensionali
a meno di specificare STATICAMENTE (compilation-time) la lunghezza di
tutte le dimensioni ad eccezione di quella piu' a sinistra
(cioe' l'unica dimensione che puo' davvero essere DINAMICA)

Questo tipo di soluzione e' estremamente macchinosa (sia per il programmatore,
da scrivere, che per il compilatore, da gestire).
Una soluzione migliore e' quella di allocare un array monodimensionale
e gestirlo esplicitamente come una matrice (o un tensore multidimensionale)
come segue:
*/

int ma_s[4][3][2]; //statico
int *ma_d; //puntatore per...
ma_d = new int[4*3*2]; //...allocazione dinamica

for (int i=0; i<(4*3*2); i++) {
ma_d[i]=
0; //accesso sequenziale
}

//oppure
for (int i=0; i<2; i++) {
for (int j=0; j<3; j++) {
for (int k=0; k<4; k++) {
ma_d[i*(
4*3) + j*4 + k] = 0; //accesso fac-simile a molti indici
//equivalente nel caso statico a:
ma_s[i][j][k] = 0;
}
}
}


/*
Analizziamo il caso piu' semplice a due dimensioni:
Ogni matrice RIGHE x COLONNE puo' essere pensata come un unico
array a una dimensione, in cui gli elementi di coordinate: (r,c)
occupano il posto: (COLONNE x r) + c :

Esempio di matrice 3x4: (3 righe e 4 colonne)

0 1 2 3
4 5 6 7
8 9 10 11

Es:
Prima riga (ovvero r=0): 0 1 2 3 (ovvero: 4 x 0 + c)
Prima colonna (ovvero c=0): 0 4 8 (ovvero: 4 x r + 0)

NOTA BENE:
L'indice che corre piu' velocemente e' quello piu' a destra (in questo caso
l'indice di colonna).
*/

printf("\n");

return 0;

}


Nessun commento: