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

Container_of的定义如下:

#define OffsetOf(type, member) ((unsigned long) &(((type *)0)->member))

#define container_of(p, type, member)  ((type *) ((char *)(p) - OffsetOf(type, member)))

1、其实它的语法很简单,只是一些指针的灵活应用,它分两步:

第一步,首先定义一个临时的数据类型(通过(type, member) ((unsigned long) &(((type *)0)->member))获得)member在结构体里的相对偏移地址。

第二步,用 ((type *) ((char *)(p)减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。

其中的语法难点就是如何得出成员相对结构体的偏移量?

2、通过例子说明,如下:

#include <stdio.h>
#define OffsetOf(type, member) ((unsigned long) &(((type *)0)->member))
typedef struct
{
int num;
char ch;
float fl;
}test_struct; int main(void)
{
printf("offsetof(test_struct, num) = %d\n",
OffsetOf(test_struct, num)); printf("offsetof(test_struct, ch) = %d\n",
OffsetOf(test_struct, ch)); printf("offsetof(test_struct, fl) = %d\n",
OffsetOf(test_struct, fl)); return ;
}

  例子输出结果:

  其中代码难以理解的地方就是它灵活地运用了0地址。如果觉得&(((type *)0)->member)这样的代码不好理解,那么我们可以假设在0地址分配了一个结构体变量test_struct a,然后定义结构体指针变量p并指向a(test_struct *p = &a),如此我们就可以通过&p->member获得成员member的地址。由于a的首地址为0x0,所以成员member的首地址为0x4。

  最后通过强制类型转换(unsigned long)把一个地址值转换为一个整数。

3、 分析完container_of的定义,接下来举个例子来体会一下它的使用方法。

例子,如下:

#include <stdio.h>
#define OffsetOf(type, member) ((unsigned long) &(((type *)0)->member))
#define container_of(p, type, member) ((type *) ((char *)(p) - OffsetOf(type, member))) typedef struct
{
int num;
char ch;
float fl;
}test_struct; int main(void)
{
test_struct init_test_struct = { , 'C', 59.12 }; char *char_ptr = &init_test_struct.ch; test_struct *structs = container_of(char_ptr, test_struct, ch); printf(" test_struct->num = %d\n test_struct->ch = %c\n test_struct->fl = %f\n",
structs->num, structs->ch, structs->fl); return ;
}

  输出结果:

  由此我们知道:#define container_of(p, type, member)  ((type *) ((char *)(p) - OffsetOf(type, member))) ,我们知道结构体type的地址为:结构体type的成员member的地址减去member的相对地址。这里(type *) ((char *)(p)指的是结构体type成员member的地址。

(十)Linux内核中的常用宏container_of的更多相关文章

  1. Linux内核中的常用宏container_of

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

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

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

  3. Linux内核中的常用宏container_of其实很简单

    http://blog.csdn.net/npy_lp/article/details/7010752 通过一个结构体变量的地址,求该结构体的首地址. #ifndef CONTAINER_OF #de ...

  4. 《C预处理》Linux内核中可变参数宏的用法

    http://blog.csdn.net/tankai19880619/article/details/12015305

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

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

  6. Linux内核中双向链表的经典实现

    概要 前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法.其中,也会涉及到Linux内核 ...

  7. Linux 内核中的 GCC 特性

    https://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/ GCC 和 Linux 是出色的组合.尽管它们是独立的软件,但是 Linux 完全依靠 ...

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

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

  9. Linux内核中常用的数据结构和算法(转)

    知乎链接:https://zhuanlan.zhihu.com/p/58087261 Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树. 链表 Linux内核代码大量使用了 ...

随机推荐

  1. ACM题目————字串数

    Description 一个A和两个B一共可以组成三种字符串:"ABB","BAB","BBA". 给定若干字母和它们相应的个数,计算一共可 ...

  2. coco2dx服务器简单例子

    实现的单个socket例子,了解socket原理. 先创建一个win32的项目(命令行的),作为服务端 // SocketServer.cpp : 定义控制台应用程序的入口点.// #include ...

  3. 关于IllegalMonitorStateException异常

    关于IllegalMonitorStateException异常: api中的解释  另请参见: Object.notify(), Object.notifyAll(), Object.wait(), ...

  4. Financial Management 分类: POJ 2015-06-11 10:51 12人阅读 评论(0) 收藏

    Financial Management Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 164431   Accepted: ...

  5. 深入Linux网络核心堆栈(对于netfilter的用法和讲解)

    http://blog.csdn.net/wswifth/article/details/5115475 注册一个hook函数是围绕nf_hook_ops数据结构的一个非常简单的操作,nf_hook_ ...

  6. hdu 3123

    GCC Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submi ...

  7. await和async关键字来写异步程序

    await和async关键字出现于.Net5.0,方便写异步程序. 例子: public class MyClass { public MyClass() { DisplayValue(); //这里 ...

  8. QT笔记之模态对话框及非模态对话框

    模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在.又有叫法是称为模式对话框,无模式对话框等.所谓模态对话框就是在其 ...

  9. 从exchange2010上面删除特定主题或特定时间的邮件

    昨天在上班的公交上接到同事电话,说他的的部门老大发错了一封邮件到另外一个同事邮箱了,问我能不 能去那个同事的邮箱里面删除,我一想,之前在网上看到过资料,到了公司趁那个误接收邮件的同事还没有来,在服务器 ...

  10. Ghostscript命令实践

    一. 将单张PDF文件igs.pdf转化为tiff文件. . gs -sDEVICE=tiffg4 -sOutputFile=igs.tiff -dMaxStripSize= igs.pdf -dAd ...