Frage

Nehmen wir an, ich habe diese Struktur:

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

und eine Funktion:

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

Wie gehe ich vor, um das zu erreichen? Ich habe so etwas ausprobiert:

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

Bearbeiten: Es ist sicher anzunehmen, dass das übergebene Widget tatsächlich ein Mitglied einer Number_Key -Struktur ist

Bearbeiten: Auf der Suche nach einer Lösung für das Problem, nicht eine andere Methode.

War es hilfreich?

Lösung

Bei nur einem Widgit* und nicht einem Widgit **, der in Dialkey übergeben wird, gibt es keine Möglichkeit, das zu tun, was Sie wollen (ein Widgit* -Wert hat keine Beziehung zur Number_key Struct). Angenommen, Sie meinen wirklich so etwas wie:

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

Microsoft verfügt über ein raffiniertes Makro für diese Art von Dingen (es hilft bei der manipulierenden Routinen, die verknüpfte Listen allgemein in C manipulieren):

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

Sie könnten dies so verwenden: SO:

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

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

Andere Tipps

Wie Michael in seiner Antwort erklärt, können Sie es nicht mit gegebenen Einschränkungen tun, da es keine Möglichkeit gibt, das Zeigerdiagramm zurückzurufen. Lassen Sie mich ein Diagramm von Objekten zeichnen (in C, nicht im Oop -Sinne), um die Dinge offensichtlicher zu machen:

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

Beachten Sie die Pfeile. Sie sind ein Weg - Sie können von einem Zeiger auf spitzen Wert "gehen", aber Sie können nicht zurück "zurückgehen". Sie können also Achtung widget Argument Ihrer Funktion, um zum zu gelangen widget Objekt, aber einmal dort, gibt es keine Möglichkeit zu sagen, wer sonst noch darauf hinweist - einschließlich aller Fälle von NUMBER_KEY Strukturen. Denken Sie darüber nach: Was wäre, wenn Sie ein Dutzend andere Hinweise auf dasselbe hätten widget, einige von ihnen von verschiedenen NUMBER_KEY Objekte? Wie könnte es möglicherweise das verfolgen, ohne eine Liste aller Zeiger in sich zu halten widget Objekt? Wenn Sie dies tatsächlich brauchen, müssen Sie es tun - machen Sie - machen Sie widget auf seinen Besitz hinweisen NUMBER_KEY.

Das Speicherlayout einer Struktur wird von Ihrem Compiler definiert. Ihr Code würde nur dann funktionieren, wenn Sie 0 Byte -Polster zwischen Strukturmitgliedern haben. Normalerweise wird dies nicht empfohlen, dass B/C 0 -Bytepolsterung Ihre Strukturüberlagerung über die Standard -Lesegrößen der meisten Prozessoren verfügt.

Einige nützliche Makros für Ihr Problem:

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

Beispiel:

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'

C Standard definiert offsetof() Makro (definiert in stddef.h Header), was in Ihrem Fall praktisch ist.

#include <stddef.h>

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

Beachten Sie, dass Sie eine bestehen müssen die Anschrift des Strukturfeldes, kein Wert!

Die sicherste Lösung besteht darin, den Zeiger auf die verwandte Nkey -Struktur in Widget zu halten

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

Alle anderen Methoden sind unsicher

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top