让我说我有这个结构:

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
}

微软有一个很棒的宏来做这种事情(它有助于能够在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);

其他提示

迈克尔在他的回答中解释说,你不能用给定的约束来做,因为没有办法“走回来”。指针图。为了使事情更加明显,让我绘制一个对象图(用C语言表示,而不是OOP意义上):

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

注意箭头。它们是单向的 - 你可以“走路”。从指向指向值的指针,但你不能“走路”背部。所以你可以使用你的函数的 widget 参数来获取 widget 对象,但是一旦那里,就没有办法告诉别人指向它 - 包括<的任何实例代码> NUMBER_KEY 结构。想想看:如果你有其他几十个指向同一小部件的指针,其中一些指针来自不同的 NUMBER_KEY 对象怎么办?如果不保留 widget 对象中所有指针的列表,它怎么可能跟踪呢?如果你真的需要这个,那就是你需要做的 - 让 widget 指向它自己的 NUMBER_KEY

结构的内存布局由编译器定义,只有在struct成员之间有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