offsetof宏:结构体成员相对结构体的偏移位置

container_of:根据结构体成员的地址来获取结构体的地址

offsetof 宏

原型:

#define offsetof(TYPE, MEMBER)	((size_t)&((TYPE *)0)->MEMBER)

(TYPE *)0非常巧妙,告诉编译器有一个指向结构体 TYPE 的指针,其地址是0,然后取该指针的 MEMBER 地址 &((TYPE *)0)->MEMBER,因为基址是0,所以这时获取到的 MEMBER 的地址就是相当于在结构体 TYPE 中的偏移量了。

Example:

#include <stdlib.h>
#include <stdio.h>
#include <stddef.h> struct TYPE{
int mem;
int member;
}; int main()
{
struct TYPE type;
printf("&type = %p\n", &type);
printf("&type.member = %p\n", &type.member);
printf("&((struct type *)0)->member = %lu\n", ((size_t)&((struct TYPE *)0)->member) );
printf("offsetof(struct TYPE member) = %zd\n", offsetof(struct TYPE, member));
return 0;
}
/*
result:
&type = 0x7ffc1104a110
&type.member = 0x7ffc1104a114
&((struct type *)0)->member = 4
offsetof(struct TYPE member) = 4
*/

container_of 宏

原型:linux-4.18.5

/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({ \
void *__mptr = (void *)(ptr); \
BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
!__same_type(*(ptr), void), \
"pointer type mismatch in container_of()"); \
((type *)(__mptr - offsetof(type, member))); })

网上所见更多是底下这个版本:

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

第一部分:void *__mptr = (void *)(ptr); const typeof( ((type *)0)->member ) *__mptr = (ptr);

两个的差别在于 __mptr 的类型一个是 void * ,一个是 type *。

void * 较为容易理解,下面来看看 type *:

关于 typeof 关键字其作用是返回变量的类型,简单理解就是如下,详细可参见GCC typeof在kernel中的使用——C语言的“编译时多态”

int a;
typeof(a) b; //这等同于int b;
typeof(&a) c; //这等同于int* c;

因此const typeof( ((type *)0)->member ) *__mptr = (ptr); 的作用就是通过 typeof 获取结构体成员 member 的类型,然后定义一个这个类型的指针变量 __mptr 并将其赋值为 ptr。

第二部分:(type *)( (char *)__mptr - offsetof(type,member) ),通过offsetof宏计算出 member 在 type 中的偏移,然后用 member 的实际地址__mptr减去偏移,得到 type 的起始地址。从上面关于offsetof宏的 Example 也可以验证这一点:

&type.member = 0x7ffc1104a114 - &((struct type *)0)->member = 4 = &type = 0x7ffc1104a110

offsetof与container_of宏分析的更多相关文章

  1. 对offsetof、 container_of宏和结构体的理解

    offsetof 宏 #include<stdio.h> #define offsetoff(type, member)      ((int)&((type*)0)->me ...

  2. linux中offsetof与container_of宏定义

    linux内核中offsetof与container_of的宏定义 #define offsetof(TYPE, MEMBER)    ((size_t) &((TYPE *)0)->M ...

  3. (转)offsetof与container_of宏[总结]

    1.前言 今天在看代码时,遇到offsetof和container_of两个宏,觉得很有意思,功能很强大.offsetof是用来判断结构体中成员的偏移位置,container_of宏用来根据成员的地址 ...

  4. offsetof与container_of宏[总结]

    1.前言 今天在看代码时,遇到offsetof和container_of两个宏,觉得很有意思,功能很强大.offsetof是用来判断结构体中成员的偏移位置,container_of宏用来根据成员的地址 ...

  5. 【转】container_of宏 分析

    在学习Linux驱动的过程中,遇到一个宏叫做container_of.该宏定义在include/linux/kernel.h中,首先来贴出它的代码: /** * container_of - cast ...

  6. container_of宏

    title: container_of宏 date: 2019/7/24 15:49:26 toc: true --- container_of宏 解析 在linux链表结构中有这样一个宏,通过成员变 ...

  7. container_of宏定义分析---linux内核

    问题:如何通过结构中的某个变量获取结构本身的指针??? 关于container_of宏定义在[include/linux/kernel.h]中:/*_** container_of - cast a ...

  8. 内核中container_of宏的详细分析【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637597.html 内核中container_of宏的详细分析 16年2月28日09:00:37 内核中 ...

  9. linux内核container_of宏定义分析

    看见一个哥们分析container_of很好,转来留给自己看 一.#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMB ...

随机推荐

  1. vue history模式下的微信分享

    // 微信验证 export function requireConfig() { let url = window.location.href systemApi.wxoption({ url: u ...

  2. 设计模式Design Pattern(4) -- 访问者模式

    什么是访问者模式? 一个对象有稳定的数据结构,却为不同的访问者提供不同的数据操作,对象提供接收访问者的方法,从而保证数据结构的稳定性和操作的多样性.也可以理解为,封装对象的操作方法,达到不改变对象数据 ...

  3. Linux基本命令+Makefile

    1.linux下查看进程占用cpu的情况(top): 格式 top [-] [d delay] [q] [c] [S] [s] [i] [n] 主要参数 d:指定更新的间隔,以秒计算. q:没有任何延 ...

  4. JS收缩展开效果

    // 收缩展开效果 $(document).ready(function () { $(".box h2").toggle(function () { $(this).next(& ...

  5. Redis实战(十五)Redis实现接口调用频率限制

    序言 登录次数 资料

  6. Redis实战(十三)Redis的三种集群方式

    序言 能聊聊redis cluster集群模式的原理吗 资料 https://www.cnblogs.com/51life/p/10233340.html Redis 集群分片原理

  7. WEB上传大文件

    众所皆知,web上传大文件,一直是一个痛.上传文件大小限制,页面响应时间超时.这些都是web开发所必须直面的. 本文给出的解决方案是:前端实现数据流分片长传,后面接收完毕后合并文件的思路.下面贴出简易 ...

  8. C++ 值传递、指针传递、引用传递

    1.值传递 (1)形参是实参的拷贝(这句话说明形参和实参是两个实体),改变形参的值并不会影响外部实参的值. (2)从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,不能传 ...

  9. gridbagsizer

    #coding:utf-8 import wx labels='1 2 3 4 5 6 7 8 9 '.split() class TestFrame(wx.Frame): def __init__( ...

  10. Windows10系统内置Linux

    主要是在等电脑安装系统,有点慢,于是写个博客…… 还是那句话,从今年开始NOIP应该就不让用Windows了,所以还是尽早转Linux吧,不然NOIP考场上不会编译太尴尬对吧. 在学校电脑有Linux ...