函式原型:
#define containing_record(address, type, field) ((type *)( \
(pchar)(address) - \
(ulong_ptr)(&((type *)0)->field)))
引數:
address:指向type型別結構例項中某域(成員)的指標
field:type型別結構包含的域(成員)的名稱
使用:包含windows.h標頭檔案之後即可使用
例子:
#include "stdafx.h"
#include #include using namespace std;
int main()
; abcd abcd = ;
//假設我們知道abcd結構體中b的位址和名稱求整個
//b所在結構體abcd的指標
abcd *pabcd = containing_record(&abcd.b, abcd, b);
printf("求得abcd中a:%d b:%d c:%d d:%d\n", pabcd->a, pabcd->b, pabcd->c, pabcd->d);
#if 0
這是如何做到的呢?我們來看看containing_record的表示式:
((type *)( (pchar)(address) - (ulong_ptr)(&((type *)0)->field)))
我們看最後一部分(&((type *)0)->field)將0空指標轉成type取位址在本例
就是將空指標轉成abcd*然後指向b這個變數然後在取位址,這個操作的作用就是
假設abcd開始在0x000000記憶體位置上分配記憶體在此基礎上求b的記憶體位址,說白了
就是求得b的記憶體結構體對齊偏移量,ok求得b的位址我們轉成ulong_ptr型別,然後用實際
b的記憶體位址減去b的結構體偏移量求得結構體首位址。
即:#endif
printf("---詳解---\n");
abcd *ptest = (abcd*)0; //這種情況是允許的
int *pb = &ptest->b; //求b的記憶體位址,在結構體首位址為0的情況下b的記憶體位址其實就是自身的對齊大小偏移量
ulong_ptr offset = (ulong_ptr)pb; //轉成數字
printf("b的偏移量:%d\n", offset);
//最後用實際b的位址減b的偏移量的到結構體首位址
abcd *pfinal = (abcd*)(((char*)&abcd.b) - offset);
printf("求得abcd中a:%d b:%d c:%d d:%d\n", pfinal->a, pfinal->b, pfinal->c, pfinal->d);
return 0;
}
巢狀的 CONTAINING RECORD 巨集
第乙個containing record nport recv packet rsvd 得到了nprot rect packet rsvd link 的位址,因為nprot rect packet rsvd存於 ndis packet.protocolreserved 處,所以nprot rect ...
我對CONTAINING RECORD巨集的詳細解釋
巨集containing record的用處其實還是相當大的,而且很是方便,它的主要作用是 根據結構體中的某成員的指標來推算出該結構體的指標 下面從乙個簡單的例子開始說起 我們定義乙個結構體,同時型別化 typedef struct ss 這是乙個很簡單的結構體,沒什麼特殊的,稍微分析下該結構體 結...
c 用巨集定義乙個函式
要點 變數都用括號括起來,防止出錯,結尾不需要 在實際程式設計中,不推薦把複雜的函式使用巨集,不容易除錯。多行用 要寫好c語言,漂亮的巨集定義是非常重要的。巨集定義可以幫助我們防止出錯,提高 的可移植性和可讀性等。在軟體開發過程中,經常有一些常用或者通用的功能或者 段,這些功能既可以寫成函式,也可以...