PDA

View Full Version : [c++] * e ** ???


vermaccio
04-05-2006, 11:04
int x=20; //crea variabile intera x che vale 20

int *puntx=& x; // l'indirizzo di memoria dove era la variabile x è diventato il valore della variabile puntx

*puntx=10; //la variabile x viene modificata e non vale più 20 ma 10.

è corretto?







inoltre spesso nei listati vedo **. a che servono nei puntatori?

andbin
04-05-2006, 11:25
int x=20; //crea variabile intera x che vale 20

int *puntx=& x; // l'indirizzo di memoria dove era la variabile x è diventato il valore della variabile puntx

*puntx=10; //la variabile x viene modificata e non vale più 20 ma 10.

è corretto?Sì, è esatto.

inoltre spesso nei listati vedo **. a che servono nei puntatori?È un ulteriore livello di indirezione.
Esempio:
int x = 20;

int *px = &x;
int **ppx = &px;

**ppx = 10;

vermaccio
04-05-2006, 11:43
int x = 20; //assegna alla variabile x il valore 20

int *px = &x; //assegna alla variabile di tipo puntatore px l'indirizzo della cella di memoria in cui è la variabile x


int **ppx = &px; //che assegna?

e

int *punt = &px; //ha senso?

andbin
04-05-2006, 11:50
int x = 20; //assegna alla variabile x il valore 20

int *px = &x; //assegna alla variabile di tipo puntatore px l'indirizzo della cella di memoria in cui è la variabile xOk

int **ppx = &px; //che assegna?ppx è "un puntatore ad un puntatore ad un int".

In pratica si assegna alla variabile ppx l'indirizzo del puntatore px.
px è una variabile come le altre, quindi anch'essa ha un suo indirizzo.

int *punt = &px; //ha senso?No, &px è l'espressione che indica un "puntatore a puntatore a int" mentre punt è solo un "puntatore a int". Il compilatore si arrabbia in questi casi. ;) Ti segnalerebbe che la assegnazione è incompatibile.

vermaccio
04-05-2006, 11:59
questo, se ho ben capito, perchè px è una variabile puntatore e non una variabile nel senso stretto.

infatti è diverso dire
int x;
e
int *px;

quindi , per "estrarre" l'indirizzo, quando ho una "int" userò "*".
mentre se ho una "int*" userò "**".

int x --> *px=&x
int* px --> int **ppx = &px

esatto?

ma... se punto alla ppx... che metto TRE *?

int ***pppx = &ppx

????

andbin
04-05-2006, 12:21
questo, se ho ben capito, perchè px è una variabile puntatore e non una variabile nel senso stretto.

infatti è diverso dire
int x;
e
int *px;Sono entrambe delle variabili (nel senso generale del termine "variabile") ma x è una variabile che contiene un valore intero mentre px è una variabile "puntatore" che contiene un indirizzo.

quindi , per "estrarre" l'indirizzo, quando ho una "int" userò "*".
mentre se ho una "int*" userò "**".

int x --> *px=&x
int* px --> int **ppx = &px

esatto?Questa non l'ho capita, spiegati meglio. Per ottenere un indirizzo si usa il &, per dereferenziare un indirizzo si usa il *.

ma... se punto alla ppx... che metto TRE *?

int ***pppx = &ppxSì, è così. Tieni presente che è molto raro usare 3 livelli di indirezione.

vermaccio
04-05-2006, 12:29
mi spiego meglio:

int x=20; //e ipotizziamo che l'indirizzo di memoria dove è stoccata la x sia 7500


int *px=&x; //cioè px vale 7500 ma la variabile px è stoccata, ad esempio, in indirizzo di memoria 8500

int **ppx = &px; //cioè ppx vale 8500 ma la variabile ppx è stoccata, ad esempio, in indirizzo di memoria 9500

*px=10; //la variabile x viene modificata e non vale più 20 ma 10.

x=x+5: //la variabile x ora vale 15.

tutto esatto?

andbin
04-05-2006, 12:33
int x=20; //e ipotizziamo che l'indirizzo di memoria dove è stoccata la x sia 7500

int *px=&x; //cioè px vale 7500 ma la variabile px è stoccata, ad esempio, in indirizzo di memoria 8500

int **ppx = &px; //cioè ppx vale 8500 ma la variabile ppx è stoccata, ad esempio, in indirizzo di memoria 9500

*px=10; //la variabile x viene modificata e non vale più 20 ma 10.

x=x+5: //la variabile x ora vale 15.

tutto esatto?Sì, esatto.

andbin
04-05-2006, 13:05
Prova questo "esercizio" sui puntatori ...
void funz (int **pa, int **pb)
{
int *pt;

pt = *pa;
*pa = *pb;
*pb = pt;
}

int main (void)
{
int a = 10;
int b = 20;
int *p1 = &a;
int *p2 = &b;

/* Qui p1 punta ad 'a', p2 punta a 'b' */

funz (&p1, &p2);

*p1 = 55;
*p2 = 99;

/* Cosa contengono a e b ?? */
/* Cosa fa la funz() ?? */

return 0;
}
;)

wingman87
04-05-2006, 14:19
Scusa andbin ma quando ad esempio tu hai fatto:
int *p1 = &a;
è uguale a scrivere:
int *p1;
p1=&a;
giusto?

andbin
04-05-2006, 14:27
Scusa andbin ma quando ad esempio tu hai fatto:
int *p1 = &a;
è uguale a scrivere:
int *p1;
p1=&a;
giusto?Giusto. L'unica cosa è che nel secondo caso, se p1 è una variabile locale, non essendo subito inizializzata, contiene sicuramente "spazzatura".

vermaccio
04-05-2006, 16:30
void funz (int **pa, int **pb)
{
int *pt;

pt = *pa;
*pa = *pb;
*pb = pt;
}

int main (void)
{
int a = 10;
int b = 20;
int *p1 = &a;
int *p2 = &b;

/* Qui p1 punta ad 'a', p2 punta a 'b' */

funz (&p1, &p2);

*p1 = 55;
*p2 = 99;

/* Cosa contengono a e b ?? */
/* Cosa fa la funz() ?? */

return 0;
}


all'inizio a=10 e b=20
poi b=55 e a=99 perchè i puntatori sono stati invertiti prima della riassegnazione.

esercizio illuminante!
grazie

sei sempre un mito!
(e mi sta simpatico anche il gatto)

vermaccio
09-05-2006, 11:10
int x=20; //crea variabile intera x che vale 20

int *puntx=& x; // l'indirizzo di memoria dove era la variabile x è diventato il valore della variabile puntx


1)
ma se io per motivi di programmazione conoscessi solo
*puntx come stampo il valore "20" a cui punta il puntatore *puntx?

2)se ho una funzione:
void funzione (....., double* &variabile,...)
(notare la "&")
In questa funzione ho un ciclo for che riempie l'array "variabile"

for(int i=0; .....){
variabile[i]=qualcosa
}

Se io richiamo la funzione dal main tramite
double *puntx
funzione(..., puntx,...)

io ottengo la variabile puntx che è un array(?) di puntatori ai valori "qualcosa".

se voglio stampare a video i "qualcosa" come faccio se sono double?

printf("puntx: %g\n", puntx);

???????

andbin
09-05-2006, 11:38
int x=20; //crea variabile intera x che vale 20

int *puntx=& x; // l'indirizzo di memoria dove era la variabile x è diventato il valore della variabile puntx Ok

1)
ma se io per motivi di programmazione conoscessi solo
*puntx come stampo il valore "20" a cui punta il puntatore *puntx?In generale, quando hai un puntatore (e ammesso che il puntatore sia "valido"), per ottenere il valore puntato si usa *punt.

2)se ho creato double *posizioneX

e in una funzione ho:
void funzione (....., double* &variabile,...)
(notare la "&")
In questa funzione ho un ciclo for che riempie l'array "variabile"

for(int i=0; .....){
variabile[i]=qualcosa
}

Se io richiamo la funzione dal main tramite
double *puntx
funzione(..., puntx,...)

io ottengo la variabile puntx che è un array(?) di puntatori ai valori "qualcosa".No, alt.
Ti faccio un esempio più chiaro:
void funz (double *ptr) /* ottengo un puntatore */
{
int i;

for (i = 0; i < 10; i++)
ptr[i] = i+1; /* ptr[i] equivale a *(ptr+i) cioè accede all'elemento di indice 'i' !!! */
}

int main (void)
{
int i;
double arr[10]; /* definisco un array di 10 double */

funz (arr); /* passo a funz l'indirizzo del primo elemento!! */

for (i = 0; i < 10; i++)
printf ("%f ", arr[i]); /* stampa elemento */

return 0;
}

printf("puntx: %g\n", puntx);Guarda la documentazione della printf. Ci sono molti specificatori di formato. Per i double si può usare 'e', 'f' o 'g' (ci sono delle differenze, naturalmente).

vermaccio
09-05-2006, 11:45
eccoil mio dilemma

void funz (double* &ptr)

{
int i;

for (i = 0; i < 10; i++)
ptr[i] = 100+i; //100, 101, .. ,110
}


int main (void)
{
int i;
double* nuovo;

funz (nuovo);

//ora che contiene nuovo? come stampo il contenuto?

return 0;
}

vermaccio
09-05-2006, 11:48
Ok


Ti faccio un esempio più chiaro:
void funz (double *ptr) /* ottengo un puntatore */
{
int i;

for (i = 0; i < 10; i++)
ptr[i] = i+1; /* ptr[i] equivale a *(ptr+i) cioè accede all'elemento di indice 'i' !!! */
}

int main (void)
{
int i;
double arr[10]; /* definisco un array di 10 double */

funz (arr); /* passo a funz l'indirizzo del primo elemento!! */

for (i = 0; i < 10; i++)
printf ("%f ", arr[i]); /* stampa elemento */

return 0;
}


ptr[i] = i+1;



ptr[i], variando i da 0 a 10 varrà 1,2,...11

la funzione passa all'esterno "double *ptr" ovvero il puntatore al primo elemento che vale 1.


quando fuori della funzione stampo "printf ("%f ", arr[i]);" verrà stampato 1,2...,11.

esatto?


(questi puntatori mi stanno facendo impazzireeeeeeee)

andbin
09-05-2006, 11:55
void funz (double* &ptr)Per iniziare, si dichiara il parametro come double *ptr (senza alcun &, nota bene!!!!)

{
int i;

for (i = 0; i < 10; i++)
ptr[i] = 100+i; //100, 101, .. ,110
}Ok

int main (void)
{
int i;
double* nuovo;

funz (nuovo);

//ora che contiene nuovo? come stampo il contenuto?

return 0;
}Qui no, è sbagliato.
con double *nuovo hai dichiarato un puntatore ma senza dargli un valore. Non è inizializzato, in pratica. Molto probabilmente contiene schifezze, quindi non sai a cosa punta.
Se anche puntasse a qualcosa di valido ... l'unica cosa certa è che funz cercherebbe di scrivere su 10 double a partire dall'indirizzo passato.

andbin
09-05-2006, 11:58
ptr[i], variando i da 0 a 10 varrà 1,2,...11No, "i" va da 0 a 9 (il test è per < 10!!!).

quando fuori della funzione stampo "printf ("%f ", arr[i]);" verrà stampato 1,2...,11.

esatto?I valori stampati (usando "%f") saranno:
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 10.000000

vermaccio
09-05-2006, 11:59
bel casino.
allora.
facciamo chiarezza.
tutto è iniziato perchè ho una funzione fatta così.

void funz (double* &ptr)

{
int i;

for (i = 0; i < 10; i++)
ptr[i] = 100+i; //100, 101, .. ,110
}

per attivarla ho pensato bene di fare nel main
double* nuovo;
funz (nuovo);

però non riuscivo poi a stampare il contenuto di nuovo che in teoria doveva contenere puntatori ai valori creati nella funzione.

però se ho ban capito così non va bene.

allora che devo dare in pasto alla funzione?

la devo richiamare come dal main infilandogli dentro che double? creato come?

andbin
09-05-2006, 12:09
allora che devo dare in pasto alla funzione?

la devo richiamare come dal main infilandogli dentro che double? creato come?Prendiamo il tuo ultimo esempio:
void funz (double* ptr)
{
int i;

for (i = 0; i < 10; i++)
ptr[i] = 100+i; //100, 101, .. ,109
}Tu sai che la funzione va a scrivere su 10 double messi in sequenza (quindi un array di 10 double!!!).
Alla funzione dovrai passare un puntatore tale per cui punti ad una zona di memoria valida in cui ci sia spazio per 10 double.
Il modo più semplice è passare l'indirizzo di un array di double!!!
double arr[10];

funz (arr);
Puoi allocare della memoria:
double *punt;
punt = (double*) malloc (10*sizeof (double));

funz (punt);
Quello che deve essere chiaro è che la funzione si aspetta un puntatore valido ad un blocco di 10 double.

andbin
09-05-2006, 12:11
Precisazione:
dichiarando solamente double *nuovo hai dichiarato un puntatore e basta ma non hai creato alcun spazio per 10 double!!!!

vermaccio
09-05-2006, 12:11
ma allora perchè chi ha scritto la funzione nell'intestazione ci ha messo * & e non solo *????? per complicarsi la vita? quindi levo il & e creo un vettore nel main e gli passo quello?

vermaccio
09-05-2006, 12:20
alleluja. così funziona.


void funz (double* &ptr) //NOTA BENE LA "&"

{
int i;

for (i = 0; i < 10; i++)
ptr[i] = 100+i; //100, 101, .. ,110
}


double *punt;
punt = (double*) malloc (10*sizeof (double));

funz (punt);
robot_console_printf("punt1: %g\n", punt[0]);
robot_console_printf("punt2: %g\n", punt[1]);
robot_console_printf("punt3: %g\n", punt[2]);
...
..
.


però....
quando credevo di aver capito.. ecco che arrivi tu e mi fai capire che non ho capito un c..o! hehehe.

double *punt;
creo un puntatore.

ora devo preallocargli spazio in cui verranno messi i valori dalla funzione.
punt = (double*) malloc (10*sizeof (double));

io avevo sempre pensato che bastasse crerare un puntatore e poi lo spazio fosse AUTOMATICAMENTe assegnato al momento dell'inserimento dei valori dalla funzione.

senza
punt = (double*) malloc (10*sizeof (double));
infatti non funzinava.


questa "inizializzazione" o 2prelocazione"
punt = (double*) malloc (10*sizeof (double));
va fatta solo quando creo un puntatore o anche quando creo una variabile?

cioè:
PUNTATORE
double *punt;
punt = (double*) malloc (10*sizeof (double));

VARIABILE
double variabile;
variabile = (double*) malloc (10*sizeof (double));(mi sa che questa èp una eresia ma vorrei una conferma)

andbin
09-05-2006, 12:30
ma allora perchè chi ha scritto la funzione nell'intestazione ci ha messo * & e non solo *?????*& non significa nulla nella dichiarazione di un puntatore.

In C++ (e solo in C++, non C), è possibile usare ad esempio: double &val come parametro, che però non è un puntatore ma un "reference" (è un'altra cosa ...).

per complicarsi la vita?Sicuramente molto. ;)

quindi levo il & e creo un vettore nel main e gli passo quello?Sì, va bene. La cosa importante che deve essere chiara è che prima della chiamata a funz si deve creare in qualche modo lo "spazio" sufficiente per gli N double a cui la funzione accede per scriverci dentro!

vermaccio
09-05-2006, 12:34
*& non significa nulla nella dichiarazione di un puntatore.


ehm.... io qui lo vedo e funziona pure.... bho.
forse perchè è la dichiarazione dentro l'intestazione della funzione?

andbin
09-05-2006, 12:44
*& non significa nulla nella dichiarazione di un puntatore.


ehm.... io qui lo vedo e funziona pure.... bho.
forse perchè è la dichiarazione dentro l'intestazione della funzione?Alt ... correggo ... :fagiano:

La risposta me la sono data da solo nel mio post precedente. In C++ un parametro come double &val è un "reference", quindi double* &val credo che sia un "puntatore ad un reference" o qualcosa del genere.

Guarda .. sinceramente io il C++ lo uso (e l'ho usato) molto raramente e in questo momento non ho nemmeno a portata di mano il mio manuale del C++. Controllerò ma suppongo che sia una cosa valida ...

Comunque io dichiarerei solo double *punt. Non vedo perché complicarsi la vita con i reference! ;)

andbin
09-05-2006, 12:56
double *punt;
creo un puntatore.Ok

ora devo preallocargli spazio in cui verranno messi i valori dalla funzione.
punt = (double*) malloc (10*sizeof (double));Ok. Questa è una allocazione dinamica. Ma se la dimensione dell'array non è enorme ed è conosciuta a priori ... basta un semplice array double arr[10].

io avevo sempre pensato che bastasse crerare un puntatore e poi lo spazio fosse AUTOMATICAMENTe assegnato al momento dell'inserimento dei valori dalla funzione.No, questo no. Un puntatore è solo una variabile "speciale" che contiene un indirizzo e basta.
Qualunque "spazio" per i dati veri e propri va allocato in qualche modo. Dinamicamente a run-time con malloc oppure allocato sullo "stack" se ad esempio double arr[10] è locale (in una funzione).

questa "inizializzazione" o 2prelocazione"
punt = (double*) malloc (10*sizeof (double));
va fatta solo quando creo un puntatore o anche quando creo una variabile?

cioè:
PUNTATORE
double *punt;
punt = (double*) malloc (10*sizeof (double));

VARIABILE
double variabile;
variabile = (double*) malloc (10*sizeof (double));(mi sa che questa èp una eresia ma vorrei una conferma)Sì ... eresia. ;)
double variabile è una variabile double non un puntatore (a double)!

vermaccio
09-05-2006, 13:16
ok. grazie dell'illuminazione quotidiana. hehehe.

mi sa che alla fine questo post lo riordino e ne faccio una mega FAQ sui puntatori "uso pratico" :)