簡體   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