Domanda

Diciamo che ho questa struttura:

typedef struct nKey {
    int num;
    widget* widget;
} NUMBER_KEY;

e una funzione:

void dialKey(widget* widget) {
    // Need to print 'num' of the struct that this widget resides in
}

Come posso ottenere questo risultato? Ho provato qualcosa del tipo:

    printf("%d", * (int *) widget - sizeof(int)); // Failure.org

modifica: è lecito ritenere che il widget passato sia in realtà un membro di una struttura NUMBER_KEY

modifica: cerca una soluzione al problema non un altro metodo.

È stato utile?

Soluzione

Dato che solo un widgit * e non un widgit ** vengono passati a dialKey, non c'è modo di fare quello che vuoi (un valore widgit * non ha alcuna relazione con la struttura NUMBER_KEY). Supponendo che intendi davvero qualcosa del tipo:

void dialKey(widget** ppWidget) 
{    
    // Need to print 'num' of the struct that this widget resides in
}

Microsoft ha una macro elegante per fare questo tipo di cose (aiuta a poter avere routine che manipolano gli elenchi collegati in modo generico in C):

#define CONTAINING_RECORD(address, type, field) ((type *)( \
                               (PCHAR)(address) - \
                               (ULONG_PTR)(&((type *)0)->field)))

Puoi usarlo così:

NUMBER_KEY* pNumberKey = CONTAINING_RECORD( *ppWidgit, NUMBER_KEY, widgit);

printf( "%d", pNumberKey->num);

Altri suggerimenti

Come spiega Michael nella sua risposta, non puoi farlo con determinati vincoli perché non c'è modo di " tornare indietro " il grafico del puntatore. Per rendere le cose più ovvie, lasciatemi disegnare un diagramma di oggetti (in termini di C, non in senso OOP) coinvolti:

+- NUMBER_KEY --+
|  ...          | points to      
| widget field -+-----------+
|  ...          |           |
+---------------+           |   + widget +
                            +-->|  ...   |
                                |  ...   |
                            +-->|  ...   |
                            |   +--------+
                  points to |
[widget argument]-----------+

Nota le frecce. Sono a senso unico: puoi " camminare " da un puntatore a un valore appuntito, ma non puoi " walk " indietro. Quindi puoi deferire l'argomento widget della tua funzione per arrivare all'oggetto widget , ma una volta lì, non c'è modo di dire chi altro lo punti, comprese le istanze di < code> NUMBER_KEY . Pensaci: cosa succederebbe se avessi una dozzina di altri puntatori sullo stesso widget , alcuni dei quali provenienti da diversi oggetti NUMBER_KEY ? Come è possibile rintracciarlo senza tenere un elenco di tutti i puntatori all'interno dell'oggetto widget ? Se in realtà hai bisogno di questo, è quello che dovrai fare: fai in modo che widget indichi il suo NUMBER_KEY .

Il layout di memoria di una struttura è definito dal tuo compilatore, il tuo codice funzionerebbe solo se hai un riempimento di 0 byte tra i membri della struttura. Di solito questo non è raccomandato b / c Il riempimento di 0 byte avrebbe il tuo overlay di struttura attraverso le dimensioni di lettura standard della maggior parte dei processori.

Alcune macro utili per il tuo problema:

#define GET_FIELD_OFFSET(type, field)    ((LONG)&(((type *)0)->field))
#define GET_FIELD_SIZE(type, field)      (sizeof(((type *)0)->field))

Esempio:

NUMBER_KEY key;
key.num = 55;
int nOffSetWidget = GET_FIELD_OFFSET( NUMBER_KEY, widget);
int *pKeyNumAddress = (int *) &(key.widget) - nOffSetWidget );

printf("%d", * pKeyNumAddress );    // Should print '55'
La norma

C definisce la macro offsetof () (definita nell'intestazione stddef.h ), utile nel tuo caso.

#include <stddef.h>

void DialKey(widget** foo) {
    printf("%d", *((char *)foo - offsetof(struct nKey, widget)));
}

Nota che devi passare un indirizzo del campo struct, non un valore!

La soluzione più sicura è mantenere il puntatore alla relativa struttura nKey nel widget

 printf("%d", widget->myKey->num);

Tutti gli altri metodi non sono sicuri

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top