CONTAINING_RECORD
Containing record是一个在C++编程中用处很大的一种技巧,它的功能为已知结构体或类的某一成员、对象中该成员的地址以及这一结构体名或类名,从而得到该对象的基地址。
VC6新建一个单文档工程;在视类CPP文件头部添加一个结构体;
先输出一下m_2的相对地址;
void CContainView::OnDraw(CDC* pDC)
{
CContainDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CString str1;
int* v3 = (int*)(&((PMYDATA)0)->m_2);
str1.Format("%p",v3);
//printf("%p\r\n",v3);
pDC->TextOut(50, 50, str1);
}
如果是用 %d 格式化,则输出如下;
%p 我还没用过;
资料中的格式化符有,
Format用于转换的格式字符:
%c 单个字符
%d 十进制整数(int)
%ld 十进制整数(long)
%f 十进制浮点数(float)
%lf 十进制浮点数(double)
%o 八进制数
%s 字符串
%u 无符号十进制数
%x 十六进制数
然后来使用 CONTAINING_RECORD 宏;加在视类CPP文件的头部;
void CContainView::OnDraw(CDC* pDC)
{
CContainDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CString str1;
MYDATA mydata = {333,222,111};
int* v1 = &mydata.m_2;
PMYDATA v2 = CONTAINING_RECORD(v1, MYDATA, m_2);
//printf("%d %d %d\n", v2->m_1,v2->m_2,v2->m_3);
str1.Format("%d %d %d", v2->m_1,v2->m_2,v2->m_3);
pDC->TextOut(50, 50, str1);
}
由m_2获得v2,v2就是对象的地址;然后用v2来输出各个成员;如下;
在ReactOS源码分析,内核对象分析时,也会用到这一技巧;