繁体   English   中英

c结构通过偏移量获取数据

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM