0

可以说我有这个结构:

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 结构的成员

编辑:寻找问题的解决方案而不是另一种方法。

4

5 回答 5

5

正如迈克尔在他的回答中解释的那样,你不能在给定的约束下做到这一点,因为没有办法“走回”指针图。为了让事情更明显,让我画一个涉及的对象图(用 C 术语,而不是 OOP 意义上的):

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

注意箭头。它们是单向的——你可以从一个指向指向值的指针“走”,但你不能“走”回来。因此,您可以尊重widget函数的参数以获取widget对象,但是一旦到达那里,就无法知道还有谁指向它——包括NUMBER_KEY结构的任何实例。想一想:如果您有十几个其他指向相同的指针widget,其中一些来自不同的NUMBER_KEY对象怎么办?如果不在对象中保留所有指针的列表,它怎么可能跟踪widget呢?如果你真的需要这个,那就是你必须做的——widget指出它的拥有NUMBER_KEY

于 2009-07-30T20:00:42.973 回答
4

仅给定一个 widgit* 而不是 widgit** 被传递到 dialKey,没有办法做你想做的事(widgit* 值与 NUMBER_KEY 结构无关)。假设你真的是这样的:

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

微软有一个漂亮的宏来做这种事情(它有助于能够拥有在 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);
于 2009-07-30T20:08:28.213 回答
0

结构的内存布局由编译器定义,只有在结构成员之间有 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'
于 2009-07-30T20:04:39.110 回答
0

C标准定义了offsetof()宏(在stddef.h标题中定义),这在您的情况下很方便。

#include <stddef.h>

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

请注意,您必须传递结构字段的地址,而不是值!

于 2009-07-31T13:36:36.833 回答
-1

最安全的解决方案是在小部件中保留指向相关 nKey 结构的指针

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

所有其他方法都不安全

于 2009-07-30T19:58:07.877 回答