读书人

这种指针如何求解出来的

发布时间: 2013-09-18 14:17:40 作者: rapoo

这种指针怎么求解出来的?
代码来自一个demo里的片段,不发完整的了

windows里的一个宏

#define CONTAINING_RECORD(address, type, field) ((type *)( \
(PCHAR)(address) - \
(UINT_PTR)(&((type *)0)->field)))



struct CIOCPBuffer
{
WSAOVERLAPPED ol;

SOCKET sClient;// AcceptEx接收的客户方套节字

char *buff;// I/O操作使用的缓冲区
int nLen;// buff缓冲区(使用的)大小

ULONG nSequenceNumber;// 此I/O的序列号

int nOperation;// 操作类型
#define OP_ACCEPT1
#define OP_WRITE2
#define OP_READ3

CIOCPBuffer *pNext;
};

CIOCPBuffer* pBuffer = NULL;
LPOVERLAPPED lpol;

经过一些列操作后,lpol指向一块内存,这里就省去调用代码
.......
pBuffer = CONTAINING_RECORD(lpol, CIOCPBuffer, ol); 这句代码是什么意思?




[解决办法]
#define CONTAINING_RECORD(address, type, field)

((CIOCPBuffer*) ((PCHAR)(lpol) - (ULONG_PTR)(&((CIOCPBuffer*)0)->ol)))

返回一个类型为type的struct的实例的基地址,已知其结构体中名为field的字段的地址为address

这个宏的目的是当我们知道某一个 C struct 内的某个field 的 address,我们就可以反推回含有这个 address 的 C struct instance 的 address.

宏中比较特的是(&((type *)0)->field)

这是把type instance放在address 0的地方,得到field到struct一开始的偏移值,

所以把宏中的address减去这个偏移值,就是该struct instance的位址了.

另一个要注意的是,address 是被 casting 为PCHAR,再做减法运算,

(ULONG_PTR)是为了32/64bit pointer size的不同,

最后所得到的位址再casting为type*传回.
[解决办法]


ULONG_PTR

//
#if defined(_WIN64)
typedef unsigned __int64 ULONG_PTR;
#else
typedef unsigned long ULONG_PTR;
#endif
[解决办法]

偏差==(unsigned long)(&(s->field))                             -(unsigned long)&s
==(unsigned long)&s+(unsigned long)(&(((type *)0)->field)) -(unsigned long)&s
== (unsigned long)(&(((type *)0)->field))

[解决办法]
引用:
Quote: 引用:

Quote: 引用:

Quote: 引用:

CONTAINING_RECORD 根据结构体中的某成员的指针来推算出该结构体的指针!


你看,是2个指针做减法,那就说是求差值啊。

你看到 “-” 没有?

指针做减法, c/c++里则求距离。



没错,是做减法,成员的地址值减去成员的偏移量就是成员所在结构实例的地址了吧?



(UINT_PTR)( &((type *)0)->field ) 中的 &((type *)0)->field是偏差值

(UINT_PTR)(偏差值)

我的问题是: &((type *)0)->field 这个公式是怎么得到的呢?

我试图推到一下:


偏差==(unsigned long)&s - (unsigned long)(&(s->field))
==( (unsigned long) &s - (unsigned long) &s ) - ( (unsigned long)(&(s->field))-(unsigned long) &s )
==?











看下12楼的应该就能明白了。

读书人网 >C++

热点推荐