質問

この構造体があるとしましょう:

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

および関数:

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

これを達成するにはどうすればよいですか?私は次のようなものを試しました:

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

編集:渡されるウィジェットが実際にはNUMBER_KEY構造体のメンバーであると想定するのは安全です

編集:別の方法ではなく、問題の解決策を探します。

役に立ちましたか?

解決

widgit **ではなく、widgit **がdialKeyに渡されるため、希望することはできません(widgit *値はNUMBER_KEY構造体とは関係がありません)。あなたが本当に次のようなものを意味すると仮定します:

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

Microsoftには、このタイプのことを行うための気の利いたマクロがあります(Cでリンクリストを一般的に操作するルーチンを作成できるようにするのに役立ちます):

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

次のように使用できます:

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

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

他のヒント

マイケルが答えで説明したように、「戻る」方法はないため、指定された制約では実行できません。ポインターグラフ。物事をより明確にするために、関係するオブジェクトの図を(OOPの意味ではなく、Cの用語で)描いてみましょう:

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

矢印に注意してください。それらは一方向です-「歩く」ことができます;ポインタからポイントされた値へ。ただし、「歩く」ことはできません。バック。したがって、関数の widget 引数を無視して widget オブジェクトに到達できますが、一度そこに行くと、他の誰がそれを指しているかを知る方法はありません-< code> NUMBER_KEY 構造体。考えてみてください。同じ widget への他のポインタが12個ある場合、それらのいくつかは異なる NUMBER_KEY オブジェクトからのものですか? widget オブジェクト内のすべてのポインターのリストを保持せずに、どうしてそれを追跡できますか?これが実際に必要な場合は、あなたがしなければならないことです- widget が所有する NUMBER_KEY を指すようにします。

構造体のメモリレイアウトはコンパイラによって定義されます。コードは、構造体メンバー間に0バイトのパディングがある場合にのみ機能します。通常、これは推奨されませんb / c 0バイトのパディングでは、ほとんどのプロセッサの標準読み取りサイズ全体に構造体がオーバーレイされます。

問題に役立ついくつかのマクロ:

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

例:

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標準では、 offsetof()マクロ( stddef.h ヘッダーで定義)を定義しています。これは、あなたの場合に便利です。

#include <stddef.h>

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

値ではなく、構造体フィールドのアドレスを渡す必要があることに注意してください!

最も安全な解決策は、ウィジェット内の関連するnKey構造へのポインタを保持することです

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

他のすべてのメソッドは安全ではありません

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top