PDA

View Full Version : [C] - Allocazione Dinamica di strutture


EdgarVillier
07-04-2009, 20:38
Ho trovato su libro un esempio in C che non ho capito, ed'è sull'allocazione dinamica di una struct, nel libro la effettua così :

link t = malloc(sizeof * t);

Dove link è definito nel seguente modo :

typedef struct node* link; struct node{ int info; link next;}

Non capisco la sintassi in malloc(), da quello che sapevo sizeof(tipo_di_dato) accettava in ingresso il tipo di dato e lui ne restituisce la dimensione, ma qui non ho capisco lo si moltiplica per un puntatore a t??

Dalle mie conoscenze precedenti l'allocazione di una struttura aveva la seguente sintassi :

link t =(link) malloc(sizeof(node));

Dove si faceva il cast alla funzione malloc del tipo di dato da allocare con (link).

Grazie a tutti anticipatamente

Tommo
07-04-2009, 21:10
In questa espressione, se t fosse definito come "link t", ti darebbe per forza un errore... infatti malloc viene eseguito prima, e POI viene copiato il risultato dentro al nuovo "link".
Quindi quel t che sta dentro il malloc è una variabile definita in precedenza :D

Cmq è strano, non dovrebbe essere possibile chiamare due variabili allo stesso modo.

||ElChE||88
07-04-2009, 21:28
link t = malloc(sizeof * t);

t è dichiarato come link, quindi l'espressione equivalente è:

link t = malloc(sizeof * link);

* link dereferenzia link, che è un puntatore e quindi restituisce struct node

link t = malloc(sizeof struct node);

E' un metodo un po' strano per usare la malloc però...

Tommo
07-04-2009, 21:41
No non è possibile che faccia in quella maniera:

node* t;

questa espressione genera un garbage pointer, tipo 0xcdcdcdcd... t non è inizializzato.
Allo stesso modo, nell'espressione di prima t malloc serve proprio ad inizializzare t, quindi usare t nell'espressione che lo inizializza è quanto di più sbagliato.
deferenziarlo semplicemente manda tutto in crash, nel migliore dei casi...

direi che a questo punto ci serve tutto il codice :D

||ElChE||88
07-04-2009, 22:00
No non è possibile che faccia in quella maniera:

node* t;

questa espressione genera un garbage pointer, tipo 0xcdcdcdcd... t non è inizializzato.
Allo stesso modo, nell'espressione di prima t malloc serve proprio ad inizializzare t, quindi usare t nell'espressione che lo inizializza è quanto di più sbagliato.
deferenziarlo semplicemente manda tutto in crash, nel migliore dei casi...

direi che a questo punto ci serve tutto il codice :D
Prova questo:

#include <stdlib.h>
#include <stdio.h>

typedef struct node* link;
struct node { int info; link next; };

int main()
{
link t1 = malloc(sizeof * t1);
link t2 = malloc(sizeof * t2);
t1->info = 2;
t1->next = NULL;
t2->info = 5;
t2->next = NULL;

printf("%X\n", t1);
printf("%d\n", t1->info);
printf("%d\n", t1->next);
printf("%X\n", t2);
printf("%d\n", t2->info);
printf("%d\n", t2->next);
system("pause");
}

;)

Edit: Comunque il sizeof viene eseguito a compile time, quindi parlare di garbage pointers non ha senso...

Tommo
08-04-2009, 02:22
Non sapevo che il sizeof fosse eseguito a compile time :D

In più non conoscevo la sua sintassi senza parentesi...

Cmq rimane che il libro è meglio bruciarlo, quella sintassi fa schifo, ed è inutilmente complicata!
Poteva usare direttamente il typename, poteva mettere le parentesi, poteva non fare typedef di un pointer (nascondere che un pointer è un pointer è sbagliato).
Cosa aveva contro

node* t = (node*)malloc( sizeof( node ) );

Si capisce perfettamente cosa fa e fa la stessa cosa. Mah.

||ElChE||88
08-04-2009, 10:47
Cmq rimane che il libro è meglio bruciarlo, quella sintassi fa schifo, ed è inutilmente complicata!
Ma infatti... una cosa del genere scritta in un libro mi fa venire voglia di prendere a martellate nei denti l'autore. :asd:

EdgarVillier
08-04-2009, 19:50
Anzitutto, ringrazio tutti per le risposte, adesso però ho qualche altro quesito per chiarire :

link t = malloc(sizeof * t);

t è dichiarato come link, quindi l'espressione equivalente è:

link t = malloc(sizeof * link);

* link dereferenzia link, che è un puntatore e quindi restituisce struct node

quindi *link serve a deferenziare link ed a ottenere struct node.

La cosa che ancora non ho capito è perchè non è necessario fare il cast :

link t =(link) malloc(sizeof(node));

Grazie ancora

||ElChE||88
08-04-2009, 23:18
La cosa che ancora non ho capito è perchè non è necessario fare il cast :

link t =(link) malloc(sizeof(node));

Grazie ancora
In C per trasformare un void* (il tipo ritornato dalla malloc) in un qualsiasi altro puntatore non c'è bisogno del cast esplicito.
In C++ invece dovresti scriverlo.

EdgarVillier
09-04-2009, 02:13
Ok, perfetto grazie mille a tutti per avermi chiarito entrambi i dubbi. Anche se effettivamente la sintassi non è chiara adesso penso di aver capito meglio l'allocazione dinamica.