Discussione:
puntatori doppi
(troppo vecchio per rispondere)
Marco
2004-01-13 00:11:53 UTC
Permalink
Ciao a tutti
Sono all'inizio della programmazione inC.

Voreri sapere 3 cose in particolare:

-cosa significa un puntatore di questo tipo : **ptr ?????
E' un doppio puntatore ma a che cosa? cosa serve???

- La gestione del tipo void* di una funzione (void* funzione(bla bla))
mi permette di far ritornare qualunque tipo di dato, e quindi di poter usare
la stesa funzione con + tipi di dati? (interi, caratteri,ect).

- E' possibile far ritornare 2 valori ad una funzione?????


Scusate le sciocche domande, ma sono proprio all'inizio (e sto usando il
computer di mio cugino perchè il computer ancora non ce l'ho...questo la
dice lunga sulla mia preparazione! ))

Ciao e grazie!

Marco
Mattia Belletti
2004-01-13 01:34:06 UTC
Permalink
Post by Marco
Ciao a tutti
Sono all'inizio della programmazione inC.
-cosa significa un puntatore di questo tipo : **ptr ?????
E' un doppio puntatore ma a che cosa? cosa serve???
Non possiamo sapere a che cosa, dato che tu non l'hai scritto :).
Nel senso che, normalmente, troverai dichiarazioni del tipo:
int **ptr;
il che vuol dire: un puntatore ad una variabile puntatore-ad-int.
char **ptr avra' un significato analogo per il tipo char, ecc ecc...
ovviamente, l'espressione "**ptr" da solo, di per se', significa solo
"l'oggetto puntato dall'oggetto puntato da ptr".
Post by Marco
- La gestione del tipo void* di una funzione (void* funzione(bla bla))
mi permette di far ritornare qualunque tipo di dato, e quindi di poter usare
la stesa funzione con + tipi di dati? (interi, caratteri,ect).
Beh, si', a grandi linee.
Ovvero: il tipo void* e' un _puntatore_ (e questo dovrebbe rimanere
fisso) ad un qualunque tipo di dato. Quindi questo significa che puoi
ritornare puntatori a long, puntatori ad int, ecc...
Non e' molto giusto tornare interi, long, ecc, con cast tipo:
long int li = 'a';
return (void*)li;
perche' (se non erro) la dimensione di una variabile void* non e'
specificata, e quindi un long int, ad es... potrebbe semplicemente non
starci dentro ^_^.
Post by Marco
- E' possibile far ritornare 2 valori ad una funzione?????
Se proprio ti serve, potresti creare una struct che contiene entrambi i
valori ed usare quella per il passaggio e ritorno dei parametri.
--
/**
* Mattia Belletti - Undergraduate student @ cs.unibo.it
* ICQ: 33292311 - email: ***@cs.unibo.it
* IRC: BluShine - site(s): http://cs.unibo.it/~mbellett
* Linux registered user 299762 @ Linux registered machine 213003
*/
Marco
2004-01-13 11:07:47 UTC
Permalink
Post by Mattia Belletti
Non possiamo sapere a che cosa, dato che tu non l'hai scritto :).
int **ptr;
il che vuol dire: un puntatore ad una variabile puntatore-ad-int.
char **ptr avra' un significato analogo per il tipo char, ecc ecc...
ovviamente, l'espressione "**ptr" da solo, di per se', significa solo
"l'oggetto puntato dall'oggetto puntato da ptr".
Il problema è in un programmino semplice come questo:

#include "stdio.h"
int fun(int **q){
static int n=5;
if (*q==NULL)
*q=&n;
else {
n++;
**q=**q+n;
}
return(**q);
}

int main(void){
int i,j,k,*p=NULL;
i=fun(&p);
j = ++(*p);
k=fun(&p);
printf("%d %d %d\n",i,j,k);
}

Perchè si usa un puntatore del tipo int **q ??
Che benefici porta???
In +, eseguendo il programma, mi escono i risulati 5,6 e 14.
Sui primi 2 ok, ma non capisco del perchè esca 14...teoricamente mi dovrebbe
uscire 11... nella funziona k=fun(&p), il valore passato è 6, a cui poi gli
viene assegnato nella funzione il valore 5 (5+6=11) e riportato
quest'utlimo valore... c'è qualcosa che non ho capito sicuramente,
ma ...cos'è????

Grazie!

Marco
Angelo Paolitto
2004-01-13 11:27:17 UTC
Permalink
Post by Marco
#include "stdio.h"
int fun(int **q){
static int n=5;
if (*q==NULL)
*q=&n;
else {
n++;
**q=**q+n;
}
return(**q);
}
Perchè si usa un puntatore del tipo int **q ??
Che benefici porta???
Ad es. si possono dare 6 anni di galera all'autore del codice e
dormire tranquilli la notte.
Post by Marco
In +, eseguendo il programma, mi escono i risulati 5,6 e 14.
Sui primi 2 ok, ma non capisco del perchè esca 14...teoricamente mi dovrebbe
nella funzione viene cambiato il valore di n e quindi di **q.

Il risultato e' corretto.

HTH

C:\>iao Angelo
--
Posted via Mailgate.ORG Server - http://www.Mailgate.ORG
Mattia Belletti
2004-01-13 12:24:00 UTC
Permalink
Post by Marco
#include "stdio.h"
Perche' non #include <stdio.h>??
Post by Marco
int fun(int **q){
static int n=5;
if (*q==NULL)
*q=&n;
else {
n++;
**q=**q+n;
}
return(**q);
}
int main(void){
int i,j,k,*p=NULL;
i=fun(&p);
j = ++(*p);
k=fun(&p);
printf("%d %d %d\n",i,j,k);
}
Perchè si usa un puntatore del tipo int **q ??
Che benefici porta???
Non e' che porta "benefici", semplicemente ti permette di esprimere cose
che altrimenti non potresti fare.
Ricorda, infatti, che i puntatori consentono ad una funzione di
modificare delle variabili del codice chiamante (infatti i parametri di
una funzione sono passati per valore, e non riferimento, e quindi senza
i puntatori, tutte le modifiche che fai ai parametri vengono perse a
fine chiamata).
In questo caso, semplicemente, puoi essere interessato a voler cambiare
il valore di una variabile che ha come tipo int*. Quindi, devi passare
un puntatore a quella variabile, che guarda caso e' proprio int** :P
Infatti, nel frammento di codice che mi hai passato, la funzione vuole
modificare il suo parametro: se usasse un puntatore singolo, non lo
potrebbe fare (o meglio, se lo facesse, le sue modifiche verrebbero
perse quando esce dalla funzione e viene perso il suo ambiente locale).
Post by Marco
In +, eseguendo il programma, mi escono i risulati 5,6 e 14.
Sui primi 2 ok, ma non capisco del perchè esca 14...teoricamente mi dovrebbe
uscire 11... nella funziona k=fun(&p), il valore passato è 6,
No: gli viene passato un puntatore ad una variabile puntatore che punta
al valore 6 - e' piuttosto diverso e piu' complesso :)
Inoltre, la cosa importante e' che, se segui il codice, noti che p ora
punta alla variabile static n dentro alla funzione; quindi tu hai
passato un puntatore ad un puntatore alla variabile n, che in quel
momento contiene il valore 6.
Post by Marco
a cui poi gli
viene assegnato nella funzione il valore 5 (5+6=11)
No: le variabili statiche vengono inizializzate una sola volta (ad
inizio programma, o alla prima chiamata di funzione al max direi);
d'altronde, se non fosse cosi', le variabili statiche diventerebbero
inutili, e si comporterebbero in pratica come delle variabili locali,
con veramente pochi vantaggi (pensaci su...).
Quindi, la variabile n ha conservato il valore che aveva da prima - che
e' 6, come dicevamo.
Post by Marco
e riportato
quest'utlimo valore... c'è qualcosa che non ho capito sicuramente,
ma ...cos'è????
n++;
**q=**q+n;
}
Fa questo
- incrementa n, che quindi da 6 va a 7
- **q lo puoi leggere in questo modo: q e' un puntatore alla variabile p
del main; *q quindi e' il valore di p; p, a sua volta, e' un puntatore
alla variabile statica n, dentro la funzione in cui sei, e quindi *p e'
il valore di n, che e' 7, come dicevamo prima. Quindi **q+n e' proprio
come dire n+n! E quindi... 14 :)
**q = **q+n quindi dice di mettere nella cella di memoria **q (che
abbiamo detto essere n) il valore calcolato - e quindi, mette in n il
valore 14. Poco importa, pero', dato che poi **q (14) e' ritornato, ed n
viene poi ignorato.

Spero di essere stato abbastanza chiaro :P
--
/**
* Mattia Belletti - Undergraduate student @ cs.unibo.it
* ICQ: 33292311 - email: ***@cs.unibo.it
* IRC: BluShine - site(s): http://cs.unibo.it/~mbellett
* Linux registered user 299762 @ Linux registered machine 213003
*/
theAnswer
2004-01-13 08:36:09 UTC
Permalink
Una funzione che ritorna void * è utile se nn sai che tipo di dato vuoi
ritornare, ma di per se puo essere una buona idea. In fondo un puntatore,
che sia a int, a char a long a cicciobello occupa sempre i suoi bit.

Ritornando un void * ti dai la possibilita di ritornare un qualunque tipo di
puntatore.
Lo stesso malloc ha come valore di ritorno un puntatore a void che tu puoi
'casti' al tipo corretto
Mattia Belletti
2004-01-13 12:08:13 UTC
Permalink
Post by theAnswer
Una funzione che ritorna void * è utile se nn sai che tipo di dato vuoi
ritornare, ma di per se puo essere una buona idea. In fondo un puntatore,
che sia a int, a char a long a cicciobello occupa sempre i suoi bit.
Ritornando un void * ti dai la possibilita di ritornare un qualunque tipo di
puntatore.
Lo stesso malloc ha come valore di ritorno un puntatore a void che tu puoi
'casti' al tipo corretto
Come e' stato fatto notare a me qualche tempo fa, in C non serve castare
da void*: la conversione e' implicita, e a volte esplicitarla puo'
essere dannoso (ad es., puo' nascondere il fatto che ci si e'
dimenticati di includere <stdlib.h>, et similia). Quindi, sempre meglio:
int *var = malloc(size);
piuttosto che:
int *var = (int*)malloc(size);
--
/**
* Mattia Belletti - Undergraduate student @ cs.unibo.it
* ICQ: 33292311 - email: ***@cs.unibo.it
* IRC: BluShine - site(s): http://cs.unibo.it/~mbellett
* Linux registered user 299762 @ Linux registered machine 213003
*/
Antonio barbone
2004-01-13 09:21:49 UTC
Permalink
Post by Marco
-cosa significa un puntatore di questo tipo : **ptr ?????
E' un doppio puntatore ma a che cosa? cosa serve???
lo puoi usare per gli array bidimensionali allocati dinamicamente :

es:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a[10][10];
int **b;
int conta;

if ( (b=malloc(10 * sizeof(int *)))==NULL)
exit(1);

for (conta=0; conta<10; conta++)
if ( (*(b+conta)=malloc(1 * sizeof(int)))==NULL)
exit(1);

for (conta=0; conta<10; conta++)
{
a[0][conta]=conta;
*(*(b+conta))=conta*2;
}

for (conta=0; conta<10; conta++)
printf("%d * %d = %d\n",a[0][conta],a[0][conta],*(*(b+conta)));

for (conta=0; conta<10; conta++)
free(*(b+conta));

free(b);
return 0;
}
Post by Marco
Ciao e grazie!
Marco
ciao ...
--
#include <stdio.h>
int main(void){char c[]={10,65,110,116,111,110,105,111,32,98,97,114,98,111,110,
101,32,60,104,105,110,100,101,109,105,116,64,116,105,115,99,97,108,105,110,101,
116,46,105,116,62,10,10,0};printf("%s",c);return 0;}
Loading...