container_of分析--可用good【转】

简介:

转自:http://blog.csdn.net/tigerjibo/article/details/8299589

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的值是不确定的。










本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/7130862.html,如需转载请自行联系原作者

相关文章
打印文档即提示Print driver host for 32bit applications
主机win7 32位系统,打印一切正常,共享打印机后,客户机为win7 64位系统连接该共享打印机,连接成功,驱动安装正常,x64驱动,客户机打印测试页正常,但打印文档即提示Print driver host for 32bit applications。
6459 0
打印文档即提示Print driver host for 32bit applications
|
6月前
|
Linux 开发工具 Android开发
[√]leak tracer的stack address始终无法被addr2line识别
[√]leak tracer的stack address始终无法被addr2line识别
59 0
|
Ubuntu JavaScript
ubuntu 文件监视数量 Error: ENOSPC: System limit for number of file watchers reached, watch‘所在文件路径‘
vue 运行执行 npm run dev | * Error: ENOSPC: System limit for number of file watchers reached, watch’所在文件路径’ 最简单的命令 沾走就能用
136 0
ubuntu 文件监视数量 Error: ENOSPC: System limit for number of file watchers reached, watch‘所在文件路径‘
|
编解码 并行计算
wrf--运行real.exe时报错:“Could not find level above ground“ error
在修改wrf初始场资料时,如果做了带通滤波处理,会发现在运行real.exe时报错:“Could not find level above ground” error 。
wrf--运行real.exe时报错:“Could not find level above ground“ error
SAP QM 创建ROS维护检验工序,系统报错:Work center NMDC_QA plant NMDC does not exist for task list type S
SAP QM 创建ROS维护检验工序,系统报错:Work center NMDC_QA plant NMDC does not exist for task list type S
SAP QM 创建ROS维护检验工序,系统报错:Work center NMDC_QA plant NMDC does not exist for task list type S
Cloud for Customer的第一个显示的work center是怎么加载和渲染的
Cloud for Customer的第一个显示的work center是怎么加载和渲染的
81 0
Cloud for Customer的第一个显示的work center是怎么加载和渲染的
|
定位技术
Comments on task “Smart Service II: Wrap up and make it ready for Demo“
Comments on task “Smart Service II: Wrap up and make it ready for Demo“
97 0
|
网络协议 Java 容器
【报错】项目启动,仅仅报错 One or more listeners failed to start. Full details will be found in the appropriate container log file
今天spring4.3.13 项目,整合ActiveMQ的时候,项目启动在自动部署到tomcat下的时候,不能正常的部署,仅仅报错如下: Connected to server [2017-12-08 03:57:12,428] Artifact springDemo:war exploded: Artifact is being deployed, please wait.
6168 0