宏CONTAINING_RECORD的计算解析

来源:互联网 发布:红外线透视相机软件 编辑:程序博客网 时间:2024/05/17 22:47
// 宏CONTAINING_RECORD的计算解析
// 宏CONTAINING_RECORD的作用是根据结构体中的某成员的指针来推算出该结构体的指针!
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;


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


// 命名含义:
// cr:CONTAINING_RECORD 
// Test:用来测试的
struct crTest
{
int m_nVal;
double m_dVal;
char m_cVal;
};








int main()
{
crTest cr;


// 现在假设我们知道了m_dVal的地址
PCHAR p = (PCHAR)(&cr.m_dVal);
cout << "cr.m_dVal=" << &cr.m_dVal << endl;


// 假设m_dVal在crTest中的偏移量为dLen,那么:
// &cr = &cr.m_dVal - dLen




// 如何求dLen呢
// 我们可以假设crTest的一个对象的地址值为0,这样就可以计算m_dVal的偏移量了
// 这个时候m_dVal的地址值实际就是偏移量
cout << "cr.m_dVal Offset=" << &(((crTest*)0)->m_dVal) << endl;


// 我们应该把他的偏移量转换成数字来计算,其实用int, unsigned, long都可以,不过为了防止偏移量过大溢出,所以用unsigned long
// 为什么要加上(crTest*)?后面解释
cout << "Calc one &cr=" << (crTest*)((PCHAR)&cr.m_dVal - (unsigned long)&(((crTest*)0)->m_dVal)) << endl;


// 为了64位32为的兼容性,我们应该用ULONG_PTR
cout << "Calc two &cr=" << (crTest*)((PCHAR)&cr.m_dVal - (ULONG_PTR)&(((crTest*)0)->m_dVal)) << endl;

// 好了,解释下前面为什么加(crTest*),看下不加(crTest*)的结果
cout << "Calc two &cr=" << (PCHAR)&cr.m_dVal - (ULONG_PTR)&(((crTest*)0)->m_dVal) << endl;


// 乱码了,其实是cout的问题,没法正确解析,
printf("%p\n", (PCHAR)&cr);


// 为了保险终极结果
cout << "Calc &cr=" << (crTest*)((PCHAR)&cr.m_dVal - (ULONG_PTR)&(((crTest*)0)->m_dVal)) << endl;


// 对比是否正确
cout << "&cr=" << &cr << endl;

// 结束了?等等,试下CONTAINING_RECORD
cout << "CONTAINING_RECORD = " << CONTAINING_RECORD(&cr.m_dVal, crTest, m_dVal);
system("pause");
return 0;
}
原创粉丝点击