CONTAINING_RECORD宏的实现原理

在使用windows完成端口时,会使用到CONTAINING_RECORD宏,该宏的作用就是:根据结构体中的某成员的地址来推算出该结构体整体的地址,相当于一个万能公式。
下面代码的注释中,讲解了该宏的实现原理。

#include <Windows.h>
#include <stdio.h>
int main()
{
    struct T
    {
        int a;
        int b;
        int c;
    };
    //CONTAINING_RECORD宏的作用就是根据结构体中的某成员的地址来推算出该结构体整体的地址。
    T t = { 1, 2, 3 };

    //假设我们知道T结构体中b的地址和名称,求t的指针
    T *pT = CONTAINING_RECORD(&t.b, T, b);
    printf("a:%d b:%d c:%d\n", pT->a, pT->b, pT->c);

    //CONTAINING_RECORD的定义:
    //((type *)( (PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))
    //最后一部分(&((type *)0)->field) 将0(空指针)转成type,再取地址。
    //在本例中就是将空指针转成T*, 然后指向b这个变量, 然后再取地址。
    //这个操作的作用就是:假设T开始在0x000000内存位置上分配内存,在此基础上求b的内存地址,
    //这样等同于求得b的内存结构体对齐偏移量, 求得b的地址我们转成ULONG_PTR类型,
    //然后用实际b的内存地址减去b的结构体偏移量求得结构体首地址。
    //
    //分解开来就是:

    //这种情况是允许的。
    //这个大前提很重要!!!
    T *pTemp = (T*)0;

    //求b的内存地址,在结构体首地址为0的情况下b的内存地址其实就是自身的对齐大小偏移量!!!
    //CONTAINING_RECORD宏的核心!!!
    int *pB = &pTemp->b;

    ULONG_PTR Offset = (ULONG_PTR)pB; //转成数字, 就是b的偏移量。
    printf("b的偏移量:%d\n", Offset);

    //因为各个成员的地址是递增的,最后用实际b的地址减b的偏移量的到结构体首地址
    T *pFinal = (T*)(((char*)&t.b) - Offset);
    printf("T中a:%d b:%d c:%d\n", pFinal->a, pFinal->b, pFinal->c);

    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

china_jeffery

你的鼓励是我前进的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值