[DOMANDA] Indirezione Doppia (C)

JDany

Utente Attivo
#1
Salve. Sto studiando le liste, pile, code e alberi in C.
Nel mio libro utilizza queste strutture dinamiche con un puntatore a puntatore, ma non riesco a capire il motivo per cui lo usa.

Perchè una indirezione doppia al posto di una singola indirezione?
 

rodhellas

Utente Attivo
1,440
382
Hardware Utente
CPU
Intel i5 3470
Scheda Madre
AsRock H77 pro4/mvp
Hard Disk
120GB SSD + 1TB HD
RAM
12GB Corsair XMS3 1333mhz
Scheda Video
Gigabyte GTX 960 OC
Scheda Audio
Integrata
Monitor
SyncMaster 223BW
Alimentatore
Antec HCG-520M
Case
Thermaltake Commander Ms-i Snow Edition
Sistema Operativo
Windows 10 64bit
#2
Senza un esempio è difficile darti una motivazione precisa del perchè..
 

JDany

Utente Attivo
#3
Come esempio prendo una funzione creata nell'esempio del mio libro:

C:
// header ...

struct listNode{
    char data;
    struct listNode *nextPtr; // puntatore al nodo
};

typedef struct listNode ListNode;
typedef ListNode *ListNodePtr;

void insert(ListNodePtr *sPtr, char value);

int main(void){
   
    // codice
   
    return 0;
}

void insert(ListNodePtr *sPtr, char value){
    ListNodePtr newPtr = malloc(sizeof(ListNode)); // Crea il nodo, ma viene usato una sola indirezione
   
    if(newPtr != NULL){
        newPtr->data = value;
        newPtr->nextPtr = NULL; // il nodo non è collegato ad altri nodi
       
        ListNodePtr previousPtr = NULL;
        ListNodePtr currentPtr = *sPtr;
       
        while(currentPtr != NULL && value > currentPtr->data){
            previousPtr = currentPtr;
            currentPtr = currentPtr->nextPtr; // nodo successivo
        }
       
        // Inserisci il nuovo nodo all'inizio della lista
        if(previousPtr == NULL){
            newPtr->nextPtr = *sPtr;
            *sPtr = newPtr;
        }else{
            previousPtr->nextPtr = newPtr;
            newPtr->nextPtr = currentPtr;
        }
    }else{
        printf("%s: %c %s", "Memoria esaurita!", value, "non e' stato inserito.");
    }
}
 
Ultima modifica:

_Achille

Utente Attivo
2,948
672
Hardware Utente
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Cooler Master XT; Razer Abyssus
Sistema Operativo
Windows 10 Pro
#4
Scusami ma non vedo alcun puntatore a puntatore...
 

JDany

Utente Attivo
#5
Scusami ma non vedo alcun puntatore a puntatore...
Il puntatore a puntatore in questo caso non è dichiarato in questo modo: const void ** (esempio).

Nel mio caso è dichiarato così:
Puntatore alla struttura listNode: "typedef ListNode *ListNodePtr";
Puntatore a puntatore: void insert(ListNodePtr *sPtr, char value) {}

Già ListNodePtr è un puntatore ad una struttura, mentre nella funzione insert() è dichiarato un puntatore a un puntatore a una struct listNode.

Spero di essermi spiegato.
 

_Achille

Utente Attivo
2,948
672
Hardware Utente
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
Hard Disk
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
Scheda Video
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
Alimentatore
RM550X
Case
NZXT S340
Periferiche
Cooler Master XT; Razer Abyssus
Sistema Operativo
Windows 10 Pro
#6
Il puntatore a puntatore in questo caso non è dichiarato in questo modo: const void ** (esempio).

Nel mio caso è dichiarato così:
Puntatore alla struttura listNode: "typedef ListNode *ListNodePtr";
Puntatore a puntatore: void insert(ListNodePtr *sPtr, char value) {}

Già ListNodePtr è un puntatore ad una struttura, mentre nella funzione insert() è dichiarato un puntatore a un puntatore a una struct listNode.

Spero di essermi spiegato.
Ah si scusami non lo avevo notato.

In realtà non mi pare necessario a meno di funzioni tipo init(datatypePtr *, ...).
 
Mi Piace: JDany

rodhellas

Utente Attivo
1,440
382
Hardware Utente
CPU
Intel i5 3470
Scheda Madre
AsRock H77 pro4/mvp
Hard Disk
120GB SSD + 1TB HD
RAM
12GB Corsair XMS3 1333mhz
Scheda Video
Gigabyte GTX 960 OC
Scheda Audio
Integrata
Monitor
SyncMaster 223BW
Alimentatore
Antec HCG-520M
Case
Thermaltake Commander Ms-i Snow Edition
Sistema Operativo
Windows 10 64bit
#7
Sperando di aver capito bene, il doppio puntatore serve per puntare al primo nodo. Personalmente io ho sempre creato una struct "testa" per puntare al primo nodo.
In generale, entrambi gli approcci hanno due vantaggi principali: 1) l'inserimento in testa è molto semplice (infatti
newPtr->nextPtr = *sPtr;
*sPtr = newPtr; )
2) hai salvato sempre un puntatore al primo nodo, quindi l'uso come in questo caso di funzioni è comodo (e in caso di cambiamenti pesanti alla lista incorri in meno problemi).
 
Mi Piace: JDany

Andretti60

Utente Attivo
3,060
1,980
Hardware Utente
#9
Poiche' la funzione insert() puo' cambiare il valore del primo parametro (sPtr, nel caso inserisci all'inizio della lista) e' ovvio che debba essere un puntarore (ossia passi il suo indirizzo invece che il suo valore). Poiche' il tipo stesso e' un puntatore, ecco che hai un puntatore di un puntatore. Questo non ha nulla a che vedere con liste o pile.
 
#10
Poiche' la funzione insert() puo' cambiare il valore del primo parametro (sPtr, nel caso inserisci all'inizio della lista) e' ovvio che debba essere un puntarore (ossia passi il suo indirizzo invece che il suo valore). Poiche' il tipo stesso e' un puntatore, ecco che hai un puntatore di un puntatore. Questo non ha nulla a che vedere con liste o pile.
E' spiegato nella sezione delle strutture dati dinamiche. L'esempio che ho scritto all'inizio serve per inserire dati in una lista.
 

Discussioni Simili


Entra

Guarda il video live di tomshardwareita su www.twitch.tv