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 ...
随机推荐
- Number()、parseInt()、parseFloat()的区别
最近在一个项目中遇到:需要在前台页面用javascript去处理很数值的计算. 各种用法都有,为了统一且保证处理方式正确,特地总结了一下相关的数值转换的用法: 作用: Number():可以用于任何数 ...
- Linux i2c子系统(四) _从i2c-s3c24xx.c看i2c控制器驱动的编写
"./drivers/i2c/busses/i2c-s3c2410.c"是3.14.0内核中三星SoC的i2c控制器驱动程序, 本文试图通过对这个程序的分析, 剥离繁复的细节, 总 ...
- ACM 阶乘的0
阶乘的0 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 计算n!的十进制表示最后有多少个0 输入 第一行输入一个整数N表示测试数据的组数(1<=N< ...
- image图片拉伸
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px "PingFang SC"; color: #1d9421 } p.p2 ...
- Java线程池ExecutorService
开篇前,我们先来看看不使用线程池的情况: new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override ...
- Node软件的安装
1.官网网址:https://nodejs.org/en/ 左边被推荐,右边最新 下载完成一键下一步直接安装,当然,如果你想修改安装目录的话当然没问题,注意:不要有英文目录 2.Window+r打开命 ...
- Python(五)编程小实例
Python(五)编程小实例 抓取网页信息,并生成txt文件内容! Python抓取网页技能--Python抓取网页就是我们常看见的网络爬虫,我们今天所要用到的就是我们Python中自带的模块,用这些 ...
- delphi处理消息的几种方式
第一种:自定义处理单条消息 unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, C ...
- java学习(二)多态中成员变量详解
今天我总结了一下java多态中成员变量的赋值与调用 举一个我当初做过的小案例: class Fu{ int num; void show(){} } class Zi extends Fu{ //in ...
- java学习笔记----数据类型,变量,常量
一.数据类型 1.基本类型(8种,又称内置数据类型).6种数字类型(byte,short,int,long,float,double),一种字符型(char),一种布尔类型(boolean). byt ...