您的位置:首页 > 大数据 > 人工智能

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 的使用方法.

在此之前, 没仔细研究过这个宏~

/// @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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: