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的更多相关文章

  1. 剖析linux内核中的宏---------container_of

    #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); ...

  2. linux内核中的宏ffs(x)

    linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/include/asm/bitops.h #define ffs(x) ({ unsigned long __ ...

  3. KSM剖析——Linux 内核中的内存去耦合

    简介: 作为一个系统管理程序(hypervisor),Linux® 有几个创新,2.6.32 内核中一个有趣的变化是 KSM(Kernel Samepage Merging)  允许这个系统管理程序通 ...

  4. Linux内核中container_of宏的详细解释

    上一节拒绝造轮子!如何移植并使用Linux内核的通用链表(附完整代码实现)我们在分析Linux内核链表的时候注意到内核在求解结构体偏移的时候巧妙的使用了container_of宏定义,今天我们来详细剖 ...

  5. Linux内核中的宏:__init and __exit

    ZZ FROM: http://blog.csdn.net/musein/article/details/742609 ======================================== ...

  6. (十)Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  7. Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  8. Linux内核中的常用宏container_of其实很简单【转】

    转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...

  9. Linux内核中的fastcall和asmlinkage宏

    代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...

随机推荐

  1. python 生成sql语句

    1. 别名 s = '' name = ['张三', '李四', '王五'] for i in range(len(name)): s += "'" + name[i] + &qu ...

  2. day74_10_21 三大认证

    一.权限六表. 一般在django中,基于用户权限访问控制的认证是RBAC(Role-Based Access Control) 还有一些基于auth的认证规则. Django框架采用的是RBAC认证 ...

  3. 2019年最新50道java基础部分面试题

    [软帝学院]1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语法,集合的语法,io 的语法,虚拟机方面的语法. 1.一个".j ...

  4. IOI2015 boxes纪念品盒

    BZOJ 4368: [IOI2015]boxes纪念品盒 BZOJ传送门 Description IOI2015开幕式正在进行最后一个环节.按计划在开幕式期间,每个代表队都将收到由主办方发放的一个装 ...

  5. UVA11374 Airport Express 正反两次最短路

    问题描述 洛谷(有翻译) 吐槽 一道坑题. 如何对待商务票 因为商务票只有一张,所以在\(k\)条边中只有一条边会被选中,很显然,最后这条边会被枚举. 如何选择使用商务票的边 假设我们正在枚举这条边, ...

  6. NOIP201310华容道

    题目描述 Description 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时 ...

  7. Java 并发系列之十三:安全发布

    1. 定义 发布对象(Publish): 使一个对象能够被当前范围之外的代码所使用 对象逸出(Escape): 一种错误的发布.当一个对象还没有构造完成时,就使它被其他线程所见 1.1 发布对象 pu ...

  8. (三十三)golang--面向对象之继承

    继承可以解决代码复用: 实现:只需要在结构体中嵌套一个匿名结构体: 结构体可以使用匿名结构体中所有字段核方法:无论是大写还是小写: 可以简化访问匿名结构体中的属性和方法: 当该结构体和匿名结构体有相同 ...

  9. HTML连载32-背景颜色、背景图片、背景填充

    一.背景 1.如何设置标签的背景颜色 (1)在CSS中有一个background-color:属性值:,就是专门用来设置标签的背景颜色. (2)取值:具体单词.RGB.RGBA.十六进制 例子: &l ...

  10. IM开发者的零基础通信技术入门(三):国人通信方式的百年变迁

    [来源申明]本文原文来自:微信公众号“鲜枣课堂”,官方网站:xzclass.com,原题为:<中国通信的百年沉浮>,本文引用时已征得原作者同意.为了更好的内容呈现,即时通讯网在收录时内容有 ...