CONTAINING_RECORD宏的实现原理
2017-12-14 12:30
453 查看
在使用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; }
相关文章推荐
- Java内存模型与Java线程的实现原理
- QQ的粘性控件的实现原理
- (3) 利用 Setter方式实现 【第一种方式】 依赖注入,编码剖析Spring依赖注入的原理
- linux软中断的实现原理
- 夜晚 暴力 十点钟 jQuery 的 extend 实现 原理
- AsyncTask实现的原理和适用的优缺点
- spring学习(十二)—事务实现的原理总结
- HashMap实现原理及源码分析
- PHP上传原理及操作实现
- 单点登录的实现原理
- Java注解实现原理及自定义注解
- Spark SQL inferSchema实现原理探微(Python)
- [Android] 任意时刻从子线程切换到主线程的实现原理及加强版
- Skinned Mesh原理解析和一个最简单的实现示例 .
- .NET 1.1中预编译ASP.NET页面实现原理浅析 [1] 自动预编译机制浅析
- WebGIS设计与实现原理
- CNN(Convolutional Neural Networks)没有原理只有实现
- zookeeper实现原理
- iPhone/Mac Objective-C内存管理教程和原理剖析 【三、@property (retain)和@synthesize的默认实现】
- 通过一个简单的音乐播放器探讨 Android Aidl 的实现原理