Windows中提供了一个宏

#define CONTAINING_RECORD (address, type, field ) ((type *)( \
(PCHAR)(address ) - \
(ULONG_PTR)(&((type *)0)->field)))

  

address : 结构体内成员实际地址
type : 结构体类型
field : 结构体内成员字段名称
 
作用: 更加提供的结构体成员地址反推结构体实例的地址。
 
宏进行的操作实际是:成员变量实际地址 - 成员变量偏移量。
 
大家可能对成员变量偏移量求解比较迷惑,首先假设一个结构体实例地址是从0开始分布的,由于成员变量的地址=结构体实例地址 + 成员变量偏移量,当结构体实例地址为0时,其指向的成员变量的地址就是成员变量的再结构体中的偏移量。
 
这技巧太NB了,不过大家可能还会有个疑惑,这个访问为什么不会出现内存越界问题呢?我刚看到时,第一反应是,为什么没有越界,后来仔细一想,哎,感叹自己对C语言的理解还不够透彻,其实后面计算偏移量时,虽然我们使用了地址0,
 
但是我们并没有存取地址中的任何值。如果我们直接把((type *)0)->field))赋值给另一个变量结构非法内存访问。
 
我们仔细捋下整个操作:
1、((type*)0) 以地址0转换为结构体实例的地址。
2、&(((type*)0)->field) 取字段field的地址,((type*)0)->field这个操作如果我们用它对其他变量赋值则直接出错,否则这只是个空操作什么也没有肯定不会出错,接着我们进行的取地址操作,这个操作相当于只是在结构体的地址基础上增加field变量的偏移量,因此根本不错在访问内存中内容的情况,只是单纯的对地址进行操作,看到这里应该理解了。
3、(ULONG_PTR)(&((type *)0)->field)))最后的转换只是为了字节对齐,使地址足够长。
 
通过汇编,我们看到其实后面求成员变量的偏移量在编译的时候编译器已经算计算好了。

CONTAINING_RECORD 宏的更多相关文章

  1. 我对CONTAINING_RECORD宏的详细解释

    宏CONTAINING_RECORD的用处其实还是相当大的, 而且很是方便, 它的主要作用是: 根据结构体中的某成员的指针来推算出该结构体的指针! 下面从一个简单的例子开始说起: 我们定义一个结构体, ...

  2. IOCP入门

    完成端口(Completion Port)详解 此文讲解最好,也很全面一下其他文章看看就行,也可不看. 单句柄数据,单IO数据 此文讲述比较清晰,可以辅助理解上文. IOCP编程之基本原理:http: ...

  3. 第10章 同步设备I/O和异步设备I/O(4)_利用I/O完成端口实现Socket通信

    I/O完成端口原理见上一篇(可点击这里) 10.5.4.4 利用I/O完成端口实现Socket通信 (1)Accept和AcceptEx流程的比较 ①采用accept方式的流程示意图如下(普通的阻塞函 ...

  4. 《天书夜读:从汇编语言到windows内核编程》七 内核字符串与内存

    1)驱动中的字符串使用如下结构: typedef struct _UNICODE_STRING{ USHORT Length; //字符串的长度(字节数) USHORT MaximumLength; ...

  5. Windows内存管理(1)--分配内核内存 和 使用链表

    1.      分配内核内存 Windows驱动程序使用的内存资源非常珍贵,分配内存时要尽量节约.和应用程序一样,局部变量是存放在栈空间中的.但栈空间不会像应用程序那么大,所以驱动程序不适合递归调用或 ...

  6. C++小技巧之CONTAINING_RECORD

    CONTAINING_RECORD Containing record是一个在C++编程中用处很大的一种技巧,它的功能为已知结构体或类的某一成员.对象中该成员的地址以及这一结构体名或类名,从而得到该对 ...

  7. Visual Studio 宏的高级用法

    因为自 Visual Studio 2012 开始,微软已经取消了对宏的支持,所以本篇文章所述内容只适用于 Visual Studio 2010 或更早期版本的 VS. 在上一篇中,我已经介绍了如何编 ...

  8. VC 中与字符串相关的宏 _T、TEXT,_TEXT、L 的作用

    CSDN原博文:http://blog.csdn.net/houkai363/article/details/8134787 遇到了:不能将参数 1 从“const char [5]”转换为“LPCT ...

  9. 【转】linux内核中writesb(), writesw(), writesl() 宏函数

    writesb(), writesw(), writesl() 宏函数 功能 : writesb()    I/O 上写入 8 位数据流数据 (1字节) writesw()   I/O  上写入 16 ...

随机推荐

  1. 百度地图LBS应用开发代码

    最近因为工作需要,领导要我将51地图API开发的一个应用迁移到百度地图,或者说用百度地图API进行重写,实现同样的功能.我先是把现有的这个51地图的应用了解了一下,然后就试着用百度地图做一些demo, ...

  2. 图片裁切插件jCrop的使用心得(四)

    在本篇中我来介绍一下jcrop如何实时展现用户裁切的效果图以及在项目中使用该插件注意的问题. 首先,你们在创建头像时,都可以在旁边实时的看到我裁切后的效果图,就如博客园. 这个是如何实现的呢,其实并不 ...

  3. 网页clientWidth等相关

    javascript代码:           function getInfo()          {          var s = "";          s += & ...

  4. js:合同-已知起始日期、年限,自动计算截止日期

    dateAddYear('2016-01-01', '3') ;//返回:2018-12-31 浏览器:ie11,ff 46.0.1(成功)360v8.1(急速模式,成功) 浏览器:360v8.1(兼 ...

  5. 根据版本的不同整理所有的绿色SQL Server

    在这篇论坛文章中,读者可以了解到如何根据不同的SQL Server版本,整理出所有版本的绿色SQL Server的具体方法,详细内容请参考下文: 1. Sqlservr.exe 运行参数 Sql Se ...

  6. python27读书笔记0.1

    --Notes: 测试环境:Windows ,python 2.7.3,python 自带的IDLE #-*- coding: utf-8 -*- # First Lesson# --- Line s ...

  7. 实例解析C++虚表

    OS:Windows 7 关键字:VS2015,C++,V-Table,虚表,虚函数. 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Tab ...

  8. jquery upload

    http://blueimp.github.io/jQuery-File-Upload/ https://github.com/blueimp/jQuery-File-Upload/wiki Back ...

  9. 蓝桥杯——FJ字符串

    FJ在沙盘上写了这样一些字符串: A1 = "A"1 A2 = "ABA"3 A3 = "ABACABA"7 A4 = "ABAC ...

  10. SQL 返回数量一定的行

    1. 限制返回的行 select top 10 * from tablename 2. 返回随机n行 select top n * from tablename order by newid()