C++小技巧之CONTAINING_RECORD
CONTAINING_RECORD
Containing record是一个在C++编程中用处很大的一种技巧,它的功能为已知结构体或类的某一成员、对象中该成员的地址以及这一结构体名或类名,从而得到该对象的基地址。
由于写法简单,它被当做一个宏来使用,写法是这样的。
#define CONTAINING_RECORD(address,type,field) \
((type*)((PCHAR)(address)-(ULONG_PTR)(&((type*)0)->field)))
这个宏运用的是地址的偏移来实现的,这里我们需要补充一个知识点:
用type*来对0进行强制类型转换(type是一个结构体名或类名)再调用其成员后,该成员的地址就等于其相对于基地址的相对地址即偏移。
typedef struct { //相对地址
int m_1; //0x0
int m_2; //0x4
int m_3; //0x8
}DATA,*PDATA;
int main()
{
int* v3 = (int*)(&((PDATA)0)->m_2);
printf("%p\r\n",v3);
//最后输出结果为4,即m_2的相对地址。
}
明白了这个就更容易理解CONTAINING_RECORD的实现了,显然,该对象的绝对地址,就等于对象中某一个成员的绝对地址减去这一成员的相对地址。而刚刚我们计算的就是这一相对地址。(ULONG_PTR)(&((type*)0)->field))
(PCHAR)(address) 则是该成员的绝对地址,最后两个相减,就得到了对象的基地址,利用这个基地址可以做很多事情。
注意取地址之后的强制类型转换
最终的实现:
typedef struct { //相对地址
int m_1; //0x0
int m_2; //0x4
int m_3; //0x8
}DATA,*PDATA;
// 利用地址的偏移和对0用结构体指针型强制类型转换来实现对结构体基地址的寻址。
//三参数:某一成员、对象中该成员的地址以及这一结构体名或类名
#define CONTAINING_RECORD(address,type,field) ((type*)((PCHAR)(address)-(ULONG_PTR)(&((type*)0)->field)))
int main()
{
DATA Data = {33,22,11};
//int* v3 = (int*)(&((PDATA)0)->m_1);
int* v1 = &Data.m_2;
PDATA v2 = CONTAINING_RECORD(v1, DATA, m_2);
printf("%d %d %d\n", v2->m_1,v2->m_2,v2->m_3);
//printf("%p\r\n", v3);
return 0;
}
//最终v2就是对象Data的地址,我们可以不使用Data就直接访问该对象的成员
C++小技巧之CONTAINING_RECORD的更多相关文章
- 前端网络、JavaScript优化以及开发小技巧
一.网络优化 YSlow有23条规则,中文可以参考这里.这几十条规则最主要是在做消除或减少不必要的网络延迟,将需要传输的数据压缩至最少. 1)合并压缩CSS.JavaScript.图片,静态资源CDN ...
- Git小技巧 - 指令别名及使用Beyond Compare作为差异比较工具
前言 本文主要写给使用命令行来操作Git的用户,用于提高Git使用的效率.至于使用命令还是GUI(Tortoise Git或VS的Git插件)就不在此讨论了,大家根据自己的的喜好选择就好.我个人是比较 ...
- 分享两个BPM配置小技巧
1.小技巧 流程图修改后发布的话版本号会+1,修改次数多了之后可能会导致版本号很高,这个时候可以将流程导出,然后删除对应的流程包再导入,发布数据模型和流程图之后,版本清零 2.小技巧 有的同事入职后使 ...
- linux系统维护时的一些小技巧,包括系统挂载新磁盘的方法!可收藏!
这里发布一些平时所用到的小技巧,不多,不过会持续更新.... 1.需要将history创建硬链接ln 全盘需要备份硬链接 ln /etc/xxx /home/xxx 2.root用户不可以远程 /et ...
- JS处理事件小技巧
今天,就分享一下我自己总结的一些JS的小技巧: ①防止鼠标选中事件 <div class="mask" onselectstart="return false&qu ...
- iOS:小技巧(不断更新)
记录下一些不常用技巧,以防忘记,复制用. 1.获取当前的View在Window的frame: UIWindow * window=[[[UIApplication sharedApplication] ...
- css小技巧(1)
1.-webkit-overflow-scrolling: touch; 解决ios滑动时无缓冲问题 2.::-webkit-scrollbar 设置ios滑动时是否显示滚动条 3.::selecti ...
- 最强 Android Studio 使用小技巧和快捷键
写在前面 本文翻译自 Android Studio Tips by Philippe Breault,一共收集了62个 Android Studio 使用小技巧和快捷键. 根据这些小技巧的使用场景,本 ...
- ios开发中的小技巧
在这里总结一些iOS开发中的小技巧,能大大方便我们的开发,持续更新. UITableView的Group样式下顶部空白处理 //分组列表头部空白处理 UIView *view = [[UIViewal ...
随机推荐
- centOS7 mini配置linux服务器(二) 配置IP
1.登录root用户,输入指令 #ip addr 可以看到除lo外的属于你的网卡配置. 2.输入 #cd /etc/sysconfig/network-scripts/ #vi if ...
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(八)mysql中文查询bug修复
写在前面的话 在测试搜索时出现的问题,mysql通过中文查询条件搜索不出数据,但是英文和数字可以搜索到记录,中文无返回记录.本文就是写一下发现问题的过程及解决方法.此bug在第一个项目中点这里还存在, ...
- Vuex 学习总结
好在之前接触过 flux,对于理解 vuex 还是很有帮助的.react 学到一半,后来因为太忙,就放弃了,现在也差不多都忘记了.不过感觉 vuex 还是跟 flux 还是有点区别的. 对于很多新手来 ...
- JVM 体系结构
JVM 是一种抽象的计算机,基于堆栈架构,它有自己的指令集和内存管理,是 Java 跨平台的依据,JVM解释执行字节码,或将字节码编译成本地代码执行.Java 虚拟机体系结构如下: Class Fil ...
- MySQL优化四(优化表结构)
body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10 ...
- WeMall的Android app商城中的wemall doraemon代码
WeMall-Android 包含SMSSDK/WeMall-Client/social_sdk_library_project三个项目以及Api目录下的client.php/update.xml接口 ...
- KoaHub.js -- 基于 Koa.js 平台的 Node.js web 快速开发框架之koahub-handlebars
koahub-handlebars koahub-handlebars koahub handlebars templates Installation $ npm install koahub-ha ...
- 4063: [Cerc2012]Darts
4063: [Cerc2012]Darts Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 85 Solved: 53[Submit][Status] ...
- 剑指offer_数组中的逆序对
题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P. 并将P对1000000007取模的结果输出. 即输出P%100 ...
- 在 sublime text 上添加 Package Control
https://packagecontrol.io/installation 打开 View > Show Consolemenu 粘贴如下文本,回车 import urllib.request ...