container_of-简易理解

详细理解http://blog.csdn.net/jacobywu/article/details/10536467


简易理解

container_of 的定义在 Linux 内核 include/linux/kernel.h 中

  1. /** 
  2.  * container_of - cast a member of a structure out to the containing structure 
  3.  * @ptr:        the pointer to the member. 
  4.  * @type:       the type of the container struct this is embedded in. 
  5.  * @member:     the name of the member within the struct. 
  6.  * 
  7.  */  
  8. #define container_of(ptr, type, member) ({                      \  
  9.         const typeof( ((type *)0)->member ) *__mptr = (ptr);    \  
  10.         (type *)( (char *)__mptr - offsetof(type,member) );})  

其中的offsetof 的定义在 include/linux/stddef.h

  1. #ifdef __compiler_offsetof  
  2. #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)  
  3. #else  
  4. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)  
  5. #endif  

在使用过程中一般不会有什么 问题,如:
  1. typedef struct frame {  
  2.         int a;  
  3.         char b;  
  4.         char name[10];  
  5. } frame_t;  
  6.   
  7. int main(int argc, char **argv)  
  8. {  
  9.         frame_t fra, *pf;  
  10.         fra.a = 1;  
  11.         fra.b = 2;  
  12.         snprintf(fra.name, 5, "cjz%d", 1);  
  13.   
  14.         pf = container_of(&fra.a, frame_t, a);  
  15.         printf("fra.a = %d, fra.b = %d, fra.name = %s\n", fra.a, fra.b, fra.name);  
  16.   
  17.         return 0;  
  18. }  

但是下边的编译的时候就会有warning

  1. typedef struct frame {  
  2.         int a;  
  3.         char b;  
  4.         char name[10];  
  5. } frame_t;  
  6.   
  7. int main(int argc, char **argv)  
  8. {  
  9.         frame_t fra, *pf;  
  10.         fra.a = 1;  
  11.         fra.b = 2;  
  12.         snprintf(fra.name, 5, "cjz%d", 1);  
  13.   
  14.         pf = container_of(fra.name, frame_t, name);  
  15.         printf("fra.a = %d, fra.b = %d, fra.name = %s\n", fra.a, fra.b, fra.name);  
  16.   
  17.         return 0;  
  18. }  
编译过程:
  1. gcc    -c -o main.o main.c  
  2. main.c: In function ‘main’:  
  3. main.c:29:57: warning: initialization from incompatible pointer type [enabled by default]  
  4. gcc -Wall  -I./ -o test main.o  


注意红色部分,这是怎么回事呢?下面我们就来分析一下

container_of的部分展开


  1. container_of(fra.name, frame_t, name) 展开如下  
  2.   
  3.  ({const typeof( ((frame_t *)0)->name ) *__mptr = (fra.name);    \  
  4.    (frame_t *)( (char *)__mptr - offsetof(frame_t, name) );})  
  5.   
  6.   
  7. 这样看来好像也没有什么 问题啊,但为什么 会有警告呢?  
  8.   
  9. 因为typeof(数组名) ,这个我个先把它称为数组名类型,而typeof( ) 中要的是一个C中定义的类型,应该为数组元素类型,所以我们这里应该传数组首元素。  
  10.   
  11. pf = container_of(fra.name, frame_t, name[0]);  
  12.   
  13. 注意红色部分与之前的不同,之前是name, 而这里是name[0]  
  14.   
  15. 改后再编译  
  16.   
  17. gcc    -c -o main.o main.c  
  18. gcc -Wall  -I./ -o test main.o  
  19.   
  20. 警告就没有了 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值