剖析linux内核中的宏-----------offsetof
offsetof用于计算TYPE结构体中MEMBER成员的偏移位置。
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
TYPE:结构体类型
MEMBER:结构体中的某一成员
分析:
1)(TYPE*)0:0被强制转换了,转换成了一个TYPE类型的结构体的指针
2)通过箭头操作,去访问MEMBER成员。问,在0地址处有个TYPE类型的结构体吗?答案肯定是没有的,因为0地址处是留给操作系统使用的。所以在0地址处绝对没有我们自定义的一个TYPE结构体变量。没有的话,这样写(TYPE *)0)->MEMBER,会不会引发程序的崩溃。现在就来讨论这个问题,要想弄明白这个问题,首先要了解编译器做了什么事情。
编译器做了什么?
编译器清楚地知道结构体成员变量的偏移位置;
通过结构体变量首地址与偏移量定位成员变量。
例如:
struct ST
{
int i ; //0
int j; //4
char c; //8
}
struct ST s = {0};
struct ST *pst = &s;
int *pi = &(pst->i); //(unsigned int )&s + 0 就是成员i的地址
int *pj = &(pst->j); //(unsigned int)&s + 4 就是成员j的地址
char *pc =&(pst->c) //(unsigned int)&s +8 就是成员c的地址
从上面可以看出,编译器根本没有真正访问pst所指向的地址中的内容,没有做任何的访问的工作。可以通过下面的成员进行验证:


如果我直接给它传一个空指针,程序会不会崩溃呢,看下面的代码:

从上面可以看出,程序不仅没有崩溃,反而把我们想要的结果打印出来,我们想要的结果就是结构体中的成员变量距离结构体首地址的偏移量。
利用offsetof这个结构体会不会实现同样的效果,继续看代码:

利用offsetof这个宏,成功的计算出了结构体中成员变量的偏移量。
总结:(TYPE *)0)->MEMBER 这个地方不会真正的去访问0地址处的内容,仅仅是编译器做了一个加法而已。用0+MEMBER在结构体中的偏移量,最后计算出一个地址。在此处该地址与MEMBER在结构体中的偏移量相等。
剖析linux内核中的宏-----------offsetof的更多相关文章
- 剖析linux内核中的宏---------container_of
#define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); ...
- linux内核中的宏ffs(x)
linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/include/asm/bitops.h #define ffs(x) ({ unsigned long __ ...
- KSM剖析——Linux 内核中的内存去耦合
简介: 作为一个系统管理程序(hypervisor),Linux® 有几个创新,2.6.32 内核中一个有趣的变化是 KSM(Kernel Samepage Merging) 允许这个系统管理程序通 ...
- Linux内核中container_of宏的详细解释
上一节拒绝造轮子!如何移植并使用Linux内核的通用链表(附完整代码实现)我们在分析Linux内核链表的时候注意到内核在求解结构体偏移的时候巧妙的使用了container_of宏定义,今天我们来详细剖 ...
- Linux内核中的宏:__init and __exit
ZZ FROM: http://blog.csdn.net/musein/article/details/742609 ======================================== ...
- (十)Linux内核中的常用宏container_of
Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...
- Linux内核中的常用宏container_of
Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...
- Linux内核中的常用宏container_of其实很简单【转】
转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...
- Linux内核中的fastcall和asmlinkage宏
代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...
随机推荐
- 元昊讲django框架
一 什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. 对于所有 ...
- 《高性能MySQL》读后感——聚簇索引
<高性能MySQL>读后感——聚簇索引 聚簇索引并不是一种单独的索引类型,而是一种数据存储方式.比如,InnoDB的聚簇索引使用B+Tree的数据结构存储索引和数据. 当表有聚簇索引时,它 ...
- Spring Cloud和Spring Boot的版本问题
很多人在使用springboot和springcloud,但是对于这两者之间的版本关系不是很清楚,特别是在面临升级的时候不知道该如何操作.本文简要摘录的官方文档的部分内容作为依据,供广大同行参考. 问 ...
- angular修改端口号port
报错:Port 4200 is already in use. Use '--port' to specify a different port. 因为4200端口已被使用,请使用“--port”修改 ...
- 动手学深度学习17-kaggle竞赛实践小项目房价预测
kaggle竞赛 获取和读取数据集 数据预处理 找出所有数值型的特征,然后标准化 处理离散值特征 转化为DNArray后续训练 训练模型 k折交叉验证 预测样本,并提交结果 kaggle竞赛 本节将动 ...
- 快速入门:Python简单实例100个(入门完整版)
Python3 100例 文章目录 Python3 100例 实例001:数字组合 实例002:“个税计算” 实例003:完全平方数 实例004:这天第几天 实例005:三数排序 实例006:斐波那契 ...
- Vue.js 源码分析(二十二) 指令篇 v-model指令详解
Vue.js提供了v-model指令用于双向数据绑定,比如在输入框上使用时,输入的内容会事实映射到绑定的数据上,绑定的数据又可以显示在页面里,数据显示的过程是自动完成的. v-model本质上不过是语 ...
- redis之通信协议
Redis 协议将传输的结构数据分为 5 种最小单元类型,单元结束时统一加上回车换行符号\r\n. 1.单行字符串 以 + 符号开头. 2.多行字符串 以 $ 符号开头,后跟字符串长度. 3.整数值 ...
- telnet 发送邮件
telnet smtp.aliyun.com 25 // 这里用的是阿里云的smpt服务器,并且开放25端口 helo hi // 和阿里云的smtp服务器打招呼,测试是否连通 auth login ...
- 大咖云集!Kubernetes and Cloud Native Meetup 深圳站开始报名!
由阿里技术生态联合 CNCF 官方共同出品的 Kubernetes & Cloud Native Meetup 将在 8 月 31 日来到深圳.届时,阿里云.蚂蚁金服高级技术专家将携手来自国内 ...