今天看代碼時,發(fā)現(xiàn)一個有用的東東,offsetof(s,m),這是一個宏,MSDN文檔的說明如下:
Retrieves the offset of a member
from the beginning of its parent structure.
size_t offsetof(
structName,
memberName
);
Parameters
structName
Name of the parent data structure.
memberName
Name of the member in the parent data structure for which to determine the
offset.
Return Value
offsetof returns the offset in bytes of the specified member from the beginning
of its parent data structure. It is undefined for bit fields.
Remarks
The offsetof macro returns the offset in bytes of memberName from the beginning
of the structure specified by structName. You can specify types with the struct
keyword.
Note
offsetof is not a function and cannot be described using a C prototype.
跟蹤代碼發(fā)現(xiàn)定義如下:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
然后到網(wǎng)上查了一下,發(fā)現(xiàn)還真的是很有用,附帶一位大俠的解說:
struct AAA
{
int i;
int j;
};
struct AAA *pAAA;
pAAA=new AAA;
這時,pAAA實際上是一個Pointer, 指向某一確定的內(nèi)存地址,比如0x1234;
而 pAAA->i 整體是一個int型變量,其地址是&(pAAA->i) ,'&'為取址運(yùn)算符;
那么&(pAAA->i)一定等于0x1234,因為i是結(jié)構(gòu)體AAA的第一個元素。
而&(pAAA->j)一定是0x1234 + 0x4 = 0x1238; 因為sizeof(int) = 4;
這個做法的巧妙之處就是:它把“0”作為上例中的pAAA,那么 &(pAAA->j)就是j的offset啦。
解析結(jié)果是:
(s *)0 ,將 0 強(qiáng)制轉(zhuǎn)換為Pointer to "s"
可以記 pS = (s *)0 ,pS是指向s的指針,它的值是0;
那么pS->m就是m這個元素了,而&(pS->m)就是m的地址,而在本例中就是offset啦
再把結(jié)果強(qiáng)制轉(zhuǎn)換為size_t型的就OK 了,size_t其實也就是int啦!!
也就是說:
0 ---> (s *)0
原來的0是數(shù)值類型,現(xiàn)在是結(jié)構(gòu)體指針類型,盡管類型變了,但其值還是不變,也就是說還是0,但這個值的意義變了,現(xiàn)在是地址,而不是數(shù)值。
&(((s *)0)->m)求出字段m的地址值,但由于首地址是0,所以&(((s *)0)->m)求出字段m相對于首地址的偏移值。