DOMANDA Indirezione Doppia (C)

JDany

Utente Attivo
461
24
CPU
Ryzen 9 3900x
Scheda Madre
ASUS H170-Pro
RAM
Corsair Vengeance LPX 2x8 GB
GPU
ZOTAC RTX 3070 TWIN EDGE OC
Monitor
Philips Gaming Monitor 24"
PSU
Corsair CX450M
Case
Sharkoon VS4-V
OS
Windows 11 Pro
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 Èlite
1,522
427
CPU
Ryzen 5 3600
Dissipatore
GELID Phantom
Scheda Madre
MSI B450 Gaming Plus Max
HDD
500GB m.2 + 2TB HDD
RAM
16GB Corsair LPX 3000mhz
GPU
Gigabyte GTX 960 OC
Audio
Integrata
Monitor
SyncMaster 223BW
PSU
Antec HCG-520M
Case
Meshify C
Net
Gigabit Fastweb
OS
Windows 10 64bit
Senza un esempio è difficile darti una motivazione precisa del perchè..
 

JDany

Utente Attivo
461
24
CPU
Ryzen 9 3900x
Scheda Madre
ASUS H170-Pro
RAM
Corsair Vengeance LPX 2x8 GB
GPU
ZOTAC RTX 3070 TWIN EDGE OC
Monitor
Philips Gaming Monitor 24"
PSU
Corsair CX450M
Case
Sharkoon VS4-V
OS
Windows 11 Pro
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 Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
Scusami ma non vedo alcun puntatore a puntatore...
 

JDany

Utente Attivo
461
24
CPU
Ryzen 9 3900x
Scheda Madre
ASUS H170-Pro
RAM
Corsair Vengeance LPX 2x8 GB
GPU
ZOTAC RTX 3070 TWIN EDGE OC
Monitor
Philips Gaming Monitor 24"
PSU
Corsair CX450M
Case
Sharkoon VS4-V
OS
Windows 11 Pro
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 Èlite
3,067
725
CPU
Intel i5-6600K @4.6 GHz
Dissipatore
Cryorig H5
Scheda Madre
ASRock Z170 Extreme 6
HDD
WesternDigital 1TB & Crucial MX200 250GB
RAM
Corsair Ven 16GB DDR4 2133MHz
GPU
Sapphire RX 580 Nitro+
Monitor
Dell S2418H
PSU
RM550X
Case
NZXT S340
Periferiche
Anne Pro 2, Razer Abyssus
OS
Windows 10 Pro
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
Reazioni: JDany

rodhellas

Utente Èlite
1,522
427
CPU
Ryzen 5 3600
Dissipatore
GELID Phantom
Scheda Madre
MSI B450 Gaming Plus Max
HDD
500GB m.2 + 2TB HDD
RAM
16GB Corsair LPX 3000mhz
GPU
Gigabyte GTX 960 OC
Audio
Integrata
Monitor
SyncMaster 223BW
PSU
Antec HCG-520M
Case
Meshify C
Net
Gigabit Fastweb
OS
Windows 10 64bit
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
Reazioni: JDany

JDany

Utente Attivo
461
24
CPU
Ryzen 9 3900x
Scheda Madre
ASUS H170-Pro
RAM
Corsair Vengeance LPX 2x8 GB
GPU
ZOTAC RTX 3070 TWIN EDGE OC
Monitor
Philips Gaming Monitor 24"
PSU
Corsair CX450M
Case
Sharkoon VS4-V
OS
Windows 11 Pro
Ah si scusami non lo avevo notato.

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

Anche a me pare non necessario, però credo che la spiegazione di @rodhellas sia corretta.
Nel mio libro dice semplicemente che è un concetto avanzato, senza dare una motivazione valida.
 

Andretti60

Utente Èlite
6,440
5,091
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.
 

JDany

Utente Attivo
461
24
CPU
Ryzen 9 3900x
Scheda Madre
ASUS H170-Pro
RAM
Corsair Vengeance LPX 2x8 GB
GPU
ZOTAC RTX 3070 TWIN EDGE OC
Monitor
Philips Gaming Monitor 24"
PSU
Corsair CX450M
Case
Sharkoon VS4-V
OS
Windows 11 Pro
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.
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili