質問
この構造体があるとしましょう:
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);
他のすべてのメソッドは安全ではありません