Question

Disons que j'ai cette structure:

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

et une fonction:

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

Comment puis-je accomplir cela? J'ai essayé quelque chose comme:

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

modifier: il est prudent de supposer que le widget transmis est en fait un membre d'une structure NUMBER_KEY

modifier: rechercher une solution au problème et non une autre méthode.

Était-ce utile?

La solution

Étant donné qu'un widgit * et non un widgit ** a été passé dans dialKey, il n'y a aucun moyen de faire ce que vous voulez (une valeur widgit * n'a pas de relation avec la structure NUMBER_KEY). En supposant que vous vouliez vraiment dire quelque chose comme:

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

Microsoft a une bonne macro pour faire ce genre de choses (cela aide d’avoir des routines manipulant génériquement des listes liées en C):

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

Vous pouvez utiliser ceci comme suit:

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

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

Autres conseils

Comme Michael l'explique dans sa réponse, vous ne pouvez pas le faire avec des contraintes données car il n'y a aucun moyen de "revenir en arrière". le graphique de pointeur. Pour rendre les choses plus évidentes, permettez-moi de dessiner un diagramme des objets (en termes C, pas au sens de la POO) impliqués:

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

Remarquez les flèches. Ils sont à sens unique - vous pouvez "marcher". d'un pointeur à une valeur précise, mais vous ne pouvez pas "marcher". retour. Ainsi, vous pouvez déférencer l'argument widget de votre fonction pour accéder à l'objet widget , mais une fois là, il est impossible de déterminer qui d'autre pointe dessus, y compris les occurrences de < code> NUMBER_KEY . Pensez-y: si vous aviez une douzaine d'autres pointeurs sur le même widget , certains d'entre eux provenant de différents objets NUMBER_KEY ? Comment pourrait-il suivre cela sans garder une liste de tous les pointeurs dans l'objet widget ? Si vous en avez réellement besoin, c’est ce que vous devrez faire: faire en sorte que widget pointe vers son propre NUMBER_KEY .

La structure mémoire d'une structure est définie par votre compilateur. Votre code ne fonctionnerait que si vous avez 0 remplissage d'octets entre les membres de la structure. Cela n’est généralement pas recommandé car un remplissage sur 0 octets aurait pour effet que votre structure soit superposée aux tailles de lecture standard de la plupart des processeurs.

Quelques macros utiles à votre problème:

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

exemple:

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'

Le standard C définit la macro offsetof () (définie dans l'en-tête stddef.h ), pratique dans votre cas.

#include <stddef.h>

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

Notez que vous devez transmettre une adresse de champ struct, et non une valeur!

La solution la plus sûre consiste à conserver le pointeur sur la structure nKey associée dans le widget

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

Toutes les autres méthodes sont dangereuses

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top