PDA

View Full Version : [C] - Liste e elementi successivi.


mjordan
22-10-2007, 22:37
Data la seguente struttura:

typedef struct MemHead {
struct MemHead * next, * prev;
} MemHead;


possiamo dedurre che si tratta di una lista bidirezionale.
Ebbene, cosa vi porta a pensare, secondo voi, che la seguente macro di preprocessore possa restituire il puntatore al nodo successivo prendendo in input un nodo di questo tipo?


#define MEMNEXT(x) ((MemHead *)(((char *) x) - ((char *) & (((MemHead *)0)->next))))


In sostanza, ne riuscite a carpire la logica?

71104
23-10-2007, 11:08
questo pezzo di codice:
((char *) & (((MemHead *)0)->next))
calcola l'offset del campo next all'interno della struttura, quindi a me pare che la macro prenda l'indirizzo di una di quelle struct e vi sottragga l'offset di quel campo, non ho idea del perché. tra l'altro capita che l'offset di next sia zero perchè è il primo campo, quindi oserei dire che la macro restituisce x così com'è. non sono neanche del tutto sicuro che la macro sia sintatticamente corretta visto che tenta di effettuare una sottrazione tra due puntatori...

mjordan
23-10-2007, 17:30
A me sfugge completamente la logica che ci sta dietro. Al calcolo dell'offset ci avevo pensato anche io, tuttavia non riesco a capire due cose:

a) Perchè usare nello specifico un casting a "char *".
b) Effettivamente non mi è chiara la sintassi della seconda parte della sottrazione, per la precisione il primo membro dell'&.

Quanto alla correttezza, ho implementato un programma di prova, tempo fa, e questo codice funzionava. Se lo trovo lo posto, devo averlo da qualche parte sparso per l'hard disk...

Tu per caso hai qualche manuale come si deve sul preprocessore e le macro?

EDIT: Perfetto, il programma che avevo fatto l'ho cancellato :muro:
Il GNU cpp Reference Manual non aiuta purtroppo, c'è scritto tutto tranne che insegnare la sintassi avanzata delle macro di preprocessore... :muro:

EDIT2: Muoio dalla voglia di vedere quanto è più efficiente fare cosi per restituire il prossimo nodo di una lista al posto del classico controllo del puntatore next. Perchè altrimenti questo è masochismo. :asd:

71104
23-10-2007, 19:59
a) Perchè usare nello specifico un casting a "char *". per castarlo ad un tipo che abbia la dimensione di un byte suppongo, altrimenti l'aritmetica dei puntatori sottrarrebbe N * sizeof anziché N.

b) Effettivamente non mi è chiara la sintassi della seconda parte della sottrazione, per la precisione il primo membro dell'&. "membro"? :wtf: forse volevi scrivere "operando"? ma guarda che non è mica un and :D

Quanto alla correttezza, ho implementato un programma di prova, tempo fa, e questo codice funzionava. Se lo trovo lo posto, devo averlo da qualche parte sparso per l'hard disk... io sinceramente non capisco come mai fare tutto quel casino quando il puntatore al prossimo nodo dovrebbe stare, a occhio, semplicemente in next... :mbe:
cioè non sarebbe possibile ridefinire quella macro come
((x)->next)
?

da dove l'hai preso sto codice?

Tu per caso hai qualche manuale come si deve sul preprocessore e le macro? no: io vado matto per i references ufficiali (MSDN Library, reference di Java, manuali dell'architettura Intel...), per conto mio non leggo praticamente nient'altro di informatica, e i "reference ufficiali" del C e del C++ purtroppo sono a pagamento.

EDIT2: Muoio dalla voglia di vedere quanto è più efficiente fare cosi per restituire il prossimo nodo di una lista al posto del classico controllo del puntatore next. Perchè altrimenti questo è masochismo. :asd: questa frase che hai scritto è illuminante: la macro non legge mai il valore di x->next (motivo percui è più efficiente: un accesso di memoria centrale in meno; capirai... :asd: ), quindi per forza di cose queste strutture MemHead devono essere disposte in memoria secondo un certo layout che fa si' che il calcolo effettuato dalla macro restituisca il puntatore alla struttura successiva.