[英]c struct grabbing data by offset
可以说我有这个结构:
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结构的成员
编辑:寻找问题的解决方案而不是另一种方法。
正如Michael在回答中解释的那样,您不能在给定的约束下完成此操作,因为无法“返回”指针图。 为了使事情更明显,让我画一个涉及的对象图(用C术语表示,而不是OOP含义):
+- NUMBER_KEY --+
| ... | points to
| widget field -+-----------+
| ... | |
+---------------+ | + widget +
+-->| ... |
| ... |
+-->| ... |
| +--------+
points to |
[widget argument]-----------+
注意箭头。 它们是单向的-您可以从指针“移动”到指向的值,但是不能“移动”回去。 因此,您可以引用函数的widget
参数来获取widget
对象,但是一旦到达该对象,就无法告诉其他人指向它了-包括NUMBER_KEY
结构的任何实例。 想一想:如果您有十二个指向同一widget
其他指针,其中有一些来自不同的NUMBER_KEY
对象,该怎么办? 如果不在widget
对象中保留所有指针的列表,如何跟踪呢? 如果您确实需要它,这就是您需要做的-使widget
指向它自己的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);
结构的内存布局是由编译器定义的,只有在结构成员之间填充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)));
}
请注意,您必须传递一个struct字段的地址 ,而不是一个值!
最安全的解决方案是在小部件中保留指向相关nKey结构的指针
printf("%d", widget->myKey->num);
所有其他方法都不安全
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.