Pregunta

Digamos que tengo esta estructura:

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

y una función:

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

¿Cómo hago para lograr esto? Intenté algo como:

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

editar: es seguro asumir que el widget que se pasa es, de hecho, miembro de una estructura NUMBER_KEY

editar: buscando una solución al problema, no otro método.

¿Fue útil?

Solución

Dado que solo se pasa un widgit * y no un widgit ** a dialKey, no hay forma de hacer lo que desea (un valor widgit * no tiene relación con la estructura NUMBER_KEY). Asumiendo que realmente quieres decir algo como:

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

Microsoft tiene una macro ingeniosa para hacer este tipo de cosas (ayuda a poder tener rutinas que manipulen las listas vinculadas genéricamente en C):

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

Puedes usar esto así:

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

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

Otros consejos

Como explica Michael en su respuesta, no puede hacerlo con las restricciones dadas porque no hay forma de "caminar de regreso". El gráfico del puntero. Para hacer las cosas más obvias, permítanme dibujar un diagrama de los objetos (en términos de C, no en sentido POO) involucrados:

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

Observe las flechas. Son unidireccionales: puedes 'caminar'. de un puntero al valor en punta, pero no puede "caminar" espalda. Por lo tanto, puede deducir el argumento widget de su función para llegar al objeto widget , pero una vez allí, no hay forma de saber quién más lo señala, incluidas las instancias de < code> NUMBER_KEY estructuras. Piénselo: ¿qué pasaría si tuviera una docena de otros punteros al mismo widget , algunos de ellos de diferentes objetos NUMBER_KEY ? ¿Cómo podría rastrear eso sin mantener una lista de todos los punteros dentro del objeto widget ? Si realmente necesita esto, es lo que tendrá que hacer: hacer que el widget apunte a su NUMBER_KEY .

El diseño de memoria de una estructura está definido por su compilador, su código solo funcionaría si tiene 0 bytes de relleno entre los miembros de la estructura. Por lo general, esto no se recomienda porque el relleno de byte de 0 bytes tendría su estructura superpuesta en los tamaños de lectura estándar de la mayoría de los procesadores.

Algunas macros útiles para su problema:

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

ejemplo:

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'
El estándar

C define la macro offsetof () (definida en el encabezado stddef.h ), que es útil en su caso.

#include <stddef.h>

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

Tenga en cuenta que debe pasar una dirección del campo de estructura, ¡no un valor!

La solución más segura es mantener el puntero a la estructura nKey relacionada en el widget

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

Todos los demás métodos son inseguros

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top