1.container_of宏

1> Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。
2>接口:
container_of(ptr, type, member) 
 ptr:表示结构体中member的地址
 type:表示结构体类型
 member:表示结构体中的成员
通过ptr的地址可以返回结构体的首地址
3> container_of的实现: 
#define container_of(ptr, type, member) ({      \   
 const typeof( ((type *)0)->member ) *__mptr = (ptr);    \  
  (type *)( (char *)__mptr - offsetof(type,member) );})  
其实它的语法很简单,只是一些指针的灵活应用,它分两步:
第一步,首先定义一个临时的数据类型(通过typeof( ((type *)0)->member )获得)与ptr相同的指针变量__mptr,然后用它来保存ptr的值。
说明:typeof是GNU C对标准C的扩展,它的作用是根据变量获取变量的类型《typeof关键字在linux 内核中很常见》
第二步,用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。
关于offsetof的用法可参见offsetof宏的使用。

2. 举例来说明container_of的使用

1>正确示例:

#include <stdio.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define  container_of(ptr, type, member) ({                      \
                      const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
                       (type *)( (char *)__mptr - offsetof(type,member) );})
struct test_struct {
           int num;
          char ch;
          float f1;
  };
 int main(void)
  {
          struct test_struct *test_struct;
          struct test_struct init_struct ={12,'a',12.3};
          char *ptr_ch = &init_struct.ch;
          test_struct = container_of(ptr_ch,struct test_struct,ch);
          printf("test_struct->num =%d\n",test_struct->num);
          printf("test_struct->ch =%c\n",test_struct->ch);
          printf("test_struct->ch =%f\n",test_struct->f1);
          return 0;
  }
执行结果:
jibo@jibo-VirtualBox:~/cv_work/work/list/container_of $ ./main
test_struct->num =12
test_struct->ch =a
test_struct->ch =12.300000

2>错误示例:

#include <stdio.h> 
  #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
  #define  container_of(ptr, type, member) ({                      \
                           const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
                          (type *)( (char *)__mptr - offsetof(type,member) );}) 
   struct test_struct {
           int num;
          char ch;
          float f1;
  }; 
  int main(void)
  {
          struct test_struct *test_struct;
          char real_ch = 'A';
          char *ptr_ch = &real_ch;
          test_struct = container_of(ptr_ch,struct test_struct,ch);
          printf("test_struct->num =%d\n",test_struct->num);
          printf("test_struct->ch =%c\n",test_struct->ch);
          printf("test_struct->ch =%f\n",test_struct->f1);
          return 0;
  }
执行结果为:
jibo@jibo-VirtualBox:~/cv_work/work/list/container_of1 $ ./main
test_struct->num =0
test_struct->ch =A
test_struct->ch =0.000000
注意,由于这里并没有使用一个具体的结构体变量,所以成员num和f1的值是不确定的。

container_of宏相关推荐

  1. linux中offsetof与container_of宏定义

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

  2. offsetof宏和container_of宏

    文章目录 1 offsetof宏 1.1 宏的作用 1.2 编译器做了什么 2 container_of宏 2.1 ({})是什么? 2.2 typeof 2.3 原理分析 1 offsetof宏 1 ...

  3. 【嵌入式】C语言高级编程-container_of宏(04)

    00. 目录 文章目录 00. 目录 01. typeof 关键字 02. typeof与宏结合 03. typeof在内核源码中应用 04. container_of 宏分析 05. contain ...

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

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

  5. (六)linux内核中的offsetof与container_of宏

    参考: offsetof与container_of宏[总结] #define offsetof(type, member) (size_t)&(((type*)0)->member)#d ...

  6. Linux字符设备驱动中container_of宏的作用

    Linux字符设备驱动中container_of宏的作用 首先看看这个宏的原型: container_of(ptr,type,member) 功能:根据一个结构体变量中的一个成员变量的指针来获取指向整 ...

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

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

  8. Linux内核中的container_of宏

    container_of宏用于根据已知结构体某个成员的地址得到整个结构体变量的地址,宏定义如下: #define container_of(ptr, type, member) ({ \ const ...

  9. Linux内核中container_of宏的理解

    对 typeof 的理解: 实际上, typeof 并不是宏定义,它是GCC的关键字,是GCC特有的特性.如果只知道一个变量的名字要得到其类型,并不是宏定义能够完成的,这需要编译时的信息.所以,typ ...

最新文章

  1. Apache优化:修改最大并发连接数
  2. 18DOM之节点操作
  3. Linux设备模型(热插拔、mdev 与 firmware)
  4. MariaDB 主从同步与热备(14)
  5. 各国家分析(马来西亚,秘鲁)
  6. Goodbye, 2010. Hello 2011...
  7. php 将前端网页输出成unicdoe编码
  8. Service Worker的应用
  9. 把可视化放到年终报告里,到底有多赞?
  10. 500 OOPS: cannot change directory:/home/xxx”
  11. 成立了汽车与智能出行事业部的阿里云,如何建立云上行业生态?
  12. linux虚拟机调整分辨率
  13. 软件工程 交互设计 信息架构设计是什么
  14. 基于微信云开发的简单商城小程序源码与配置指导
  15. RedHat免费订阅账号注册方式
  16. JDK正式免费、Log4j2爆核弹级漏洞、LayUI下线,2021的10 件大事
  17. 微软消息队列-MSMQ
  18. java构造方法中this_Java中this关键字在构造方法中的使用
  19. 707-详解32位Linux系统内存地址映射
  20. c语言设计体育打分程序,校运会成绩录入系统部分C语言源代码设计

热门文章

  1. MySQL同步状态双Yes的假象及seconds_behind_master的含义
  2. corosync+openais+pacemaker+web
  3. 公司那些事-关于领导
  4. python中seek函数的用法_在Python中操作文件之seek()方法的使用教程
  5. 深度相机之TOF原理详解
  6. C语言中auto,register,extern,static【转】
  7. ecshop pages.lbi.php,关于Ecshop pages.lbi.php Xss漏洞的修复
  8. python继承属性_Python中的属性继承问题
  9. mysql 停止服务内存_服务器莫名的内存高占用 导致 MySQL 停止运行问题
  10. bzoj3195 [Jxoi2012]奇怪的道路——状压DP