Newsgroup: it.comp.lang.c
Titolo: HELP: Puntatori a Puntatori

ciao a tutti,
chi mi da una mano a risolvere il mio dilemma?
In molte funzioni che implementano funzioni su
strutture dinamiche, vengono definiti
alcuni puntatori a puntatori come parametri formali,
ad esempio:
int cancella(NODO **rt, int x)
{
NODO *ptr;
if(*rt != NULL)
    if(x < (*rt)->key) cancella(&((*rt)->left), x);
    else
        if(x > (*rt)->key) cancella(&((*rt)->right), x);
        else
            if((*rt)->left == NULL)
                {
                 ptr = *rt;
                 *rt = (*rt)->right;
                 free(ptr);
                  }
            else
                if((*rt)->right == NULL)
                    {
                     ptr = *rt;
                     *rt = (*rt)->left;
                     free(ptr);
                 else
                     (*rt)->key = cancellamin(&((*rt)->right);
                     return;
                     }
}
Perche' viene passato un puntatore a puntatore
anziche' un semplice puntatore? Ci sono casi in cui e'
possibile passare solo un puntatore?
Ho sentito dire che passando un puntatore la funzione
che cancella un nodo da un albero binario funziona
nel 99 % dei casi, mentre l'1% dei casi necessita
di un puntatore a puntatore. In verita' io non ho
capito quale potrebbe essere.
Grazie a tutti
ciao
Luca

 capito quale potrebbe essere.
   Non e` tanto una motivazione... statistica, quanto di linguaggio. 
Come  certamente sai, i parametri delle funzioni in C sono passati per 
valore. Questo significa che le funzioni, in effetti, gestiscono una 
*copia* del parametro loro passato e non il simbolo o il letterale 
realmente specificato.
   Ora, per poter modificare il valore del simbolo passato, e` 
necessario aggirare questo meccanismo mediante il cosiddetto "passaggio 
per firefimento". Semplicemente: invece di indicare alla funzione il 
simbolo da modificare, le indichi la locazione di memoria in cui il 
simbolo e` allocato.
   Il discorso puo` essere indotto all'infinito: se vuoi modificare un 
puntatore (e non il contenuto della memoria da esso puntato) dovrai 
passare alla funzione la locazione di memoria ove il *puntatore*, inteso 
come variabile, e` allocato, ossia un puntatore a puntatore. E cosi` via.
--
Alla prossima,
Marco

anziche' un semplice puntatore? 
Perche' e' in questo modo che si implementa, in C, il
passaggio per riferimento.
Questo tipo di passaggio si applica quando vuoi modificare
un puntatore, anziche' il valore da esso puntato.
Per es., se io volessi costruire una malloc di puntatori a
interi, senza necessariamente farle restituire un valore,
potrei scrivere:
void int_malloc( int **p, size_t n )
{
     *p = malloc( n * sizeof **p ) ;
}
e poi utilizzarla con :
int *my_p ;
int_malloc( &my_p, 10 ) ;
In questo modo faccio si' che la mia funzione possa
modificare il valore di my_p.
Se io scrivessi soltanto:
void int_malloc( int *p, size_t n )
{
     p = malloc( n * sizeof *p ) ;
}
e la usassi con:
int *my_p;
int_malloc( my_p, 10 ) ;
non farei altro che allocare memoria per il puntatore p
presente nello stack della funzione, che non e' altro che la
copia del valore di my_p.
Il my_p della funzione richiamante, in realta', non verrebbe
mai modificato.
--
Andrea Laforgia - walkietalkie(at)
libero.it
http://www.geocities.com/AndreaLaforgia

 capito quale potrebbe essere.
Cos'e' questa... una domanda che viene fatta a qualche esame?
Mi pare di avere gia' letto una domanda simile.
Penso che se NODO e' definito cosi'
typedef struct nodo {
    struct nodo* left, *right;
    int key;
    ...
}NODO;
passando un puntatore a NODO si passa l'indirizzo del primo
byte di una struttura nodo, che, contenendo come primo elemento
un puntatore a nodo, e' come se si passasse un puntatore ad un
puntatore a nodo solo che e' l'indirizzo di un puntatore al ramo
sinistro dell'albero.
Per cui l'1% puo' volere dire che non si puo' cancellare la radice
o qualunque nodo nel ramo destro. Per essere piu' precisi bisognerebbe
conoscere l'effettiva definizione di NODO eppoi basta fare qualche
prova o analizzare il codice (btw ti consiglio di usare le parentesi
per ogni if /else if/ else).