experiment : how to use CONTAINING_RECORD
2013-07-02 19:27
218 查看
CONTAINING_RECORD 在应用层程序很少使用, 因为一般情况下, 都知道该结构成员所在结构的指针地址.
非回调的情况下, 一般都会传类指针或最上层的结构指针到函数.
有回调的情况下, 一般不涉及使用该结构成员父结构的问题. 使用回调的入参本身就能搞定。
用统计数据说话~, 在codeproject上搜索 CONTAINING_RECORD, 只能找到一个Demo使用了 CONTAINING_RECORD。
但是那个Demo是驱动层的Demo~
在驱动中, 有些回调函数传入了结构成员的地址, 这时就有需求知道该结构成员所在的那个结构地址,
这时可以通过 CONTAINING_RECORD, 往上回溯, 一直到找到想用的结构指针为止.
下面的Demo, 是在应用层做的. 可以验证 CONTAINING_RECORD 的使用方法.
在此之前, 没仔细研究过这个宏~
非回调的情况下, 一般都会传类指针或最上层的结构指针到函数.
有回调的情况下, 一般不涉及使用该结构成员父结构的问题. 使用回调的入参本身就能搞定。
用统计数据说话~, 在codeproject上搜索 CONTAINING_RECORD, 只能找到一个Demo使用了 CONTAINING_RECORD。
但是那个Demo是驱动层的Demo~
在驱动中, 有些回调函数传入了结构成员的地址, 这时就有需求知道该结构成员所在的那个结构地址,
这时可以通过 CONTAINING_RECORD, 往上回溯, 一直到找到想用的结构指针为止.
下面的Demo, 是在应用层做的. 可以验证 CONTAINING_RECORD 的使用方法.
在此之前, 没仔细研究过这个宏~
/// @file ... /// @brief 验证 CONTAINING_RECORD 宏的含义和正确用法 /// CONTAINING_RECORD 宏作用: 从一个结构变量的成员地址得到该结构变量的地址 #include "stdafx.h" #include <Windows.h> #include <crtdbg.h> #include <tchar.h> typedef struct _tag_PersonInfo { wchar_t cName[_MAX_PATH]; int iAge; }TAG_PERSON_INFO, *PTAG_PERSON_INFO; typedef struct _tag_TaskInfo { size_t nTaskId; ///< data type : build in TAG_PERSON_INFO Person; ///< data type : user define int iSn; ///< data type : build in }TAG_TASK_INFO, *PTAG_TASK_INFO; int _tmain(int argc, _TCHAR* argv[]) { TAG_TASK_INFO * pTaskInfo = NULL; TAG_TASK_INFO * pTaskInfo1 = NULL; TAG_TASK_INFO * pTaskInfo2 = NULL; TAG_TASK_INFO * pTaskInfo3 = NULL; TAG_PERSON_INFO * pPerson = NULL; DWORD dwOffset = 0; pTaskInfo = new TAG_TASK_INFO; _ASSERT(NULL != pTaskInfo); ::ZeroMemory(pTaskInfo, sizeof(TAG_TASK_INFO)); pTaskInfo->nTaskId = 1; pTaskInfo->Person.iAge = 99; _tcscpy_s(pTaskInfo->Person.cName, L"someOne"); pTaskInfo->iSn = 7788; /** // // Calculate the address of the base of the structure given its type, and an // address of a field within the structure. // #define CONTAINING_RECORD(address, type, field) ((type *)( \ (PCHAR)(address) - \ (ULONG_PTR)(&((type *)0)->field))) */ // /// CONTAINING_RECORD 用法 /// 宏作用: 从一个结构变量的成员地址得到该结构变量的地址 /// 参数1 : 结构变量的成员地址 /// 参数2 : 结构变量的类型 /// 参数3 : 结构变量的成员在结构定义中的成员名称 /// 返回值 结构成员所在的结构变量地址 // pTaskInfo1 = CONTAINING_RECORD(&(pTaskInfo->nTaskId), TAG_TASK_INFO, nTaskId); pTaskInfo2 = CONTAINING_RECORD(&(pTaskInfo->Person), TAG_TASK_INFO, Person); pTaskInfo3 = CONTAINING_RECORD(&(pTaskInfo->iSn), TAG_TASK_INFO, iSn); _tprintf(L"pTaskInfo = 0x%X\r\n", pTaskInfo); _tprintf(L"pTaskInfo1 = 0x%X\r\n", pTaskInfo1); _tprintf(L"pTaskInfo2 = 0x%X\r\n", pTaskInfo2); _tprintf(L"pTaskInfo3 = 0x%X\r\n", pTaskInfo3); /// 从结构变量的每一个结构成员地址,都能得到结构变量本身的唯一地址 _ASSERT(((DWORD)pTaskInfo) == ((DWORD)pTaskInfo1)); _ASSERT(((DWORD)pTaskInfo) == ((DWORD)pTaskInfo2)); _ASSERT(((DWORD)pTaskInfo) == ((DWORD)pTaskInfo3)); /** result pTaskInfo = 0x13C718 pTaskInfo1 = 0x13C718 pTaskInfo2 = 0x13C718 pTaskInfo3 = 0x13C718 */ getchar(); return 0; }
相关文章推荐
- How to use ActiveRecord in a ruby script outside Rails?
- How to use ActiveRecord without Rails
- HOW TO Use the GCC specs file
- How to use STA(sql tuning advisor)
- How To Use MCI to Play AVI/WAVE Files from Memory
- How to use MinGW Cross Compiler on Fedora
- How to use Yum package installer in linux?
- How to use Pageheap.exe in Windows XP, Windows 2000, and Windows Server 2003
- How to use tensorflow pre-trained model in Android
- xargs: How To Control and Use Command Line Arguments
- HOW to Use QP_PREQ_PUB.PRICE_REQUEST API to Price an Item
- how to use Task to represent the old Begin/End async methods
- How to use bindings-generator to generate lua binding automatically
- How to use Atlas in our Web Projects
- How to Configure iOS for iPhone and iPad to Use So
- HowTo use the CDT to navigate Linux kernel source
- [转]how to use both JDK 7 and JDK 8 in one build
- How to Use a QSqlQueryModel in QML
- how to use w3m?
- Multi-Thread 1: how to use synchronized