Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >container of()函数用法简介

container of()函数用法简介

作者头像
无刺鱼
发布于 2022-03-29 05:18:08
发布于 2022-03-29 05:18:08
1.6K00
代码可运行
举报
文章被收录于专栏:许唯宇许唯宇
运行总次数:0
代码可运行

Linux 内核编程中,会经常见到一个宏函数container_of(ptr,type,member)。已知结构体type的成员member的地址ptr,求结结构体type的起始地址。

container_of

在已知一个结构体的成员的名字,以及其地址的情况向,反推该结构体的首地址

offsetof

获取一个结构体成员在结构里面的偏移,结构体首地址 = 成员地址- 成员偏移

以下是一个container of函数例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <stdio.h>  
#include <stdlib.h>
 
#define offsetof(TYPE,MEMBER) ((int) &((TYPE *)0)->MEMBER)   //为什么这样就能得到偏移
 
#define container_of(ptr, type , member) ({ \
	const typeof(((type *)0)->member) *__mptr = (ptr) ; \
	(type *)((char *)__mptr - offsetof(type,member)) ;})
 
#pragma pack(4)  
struct ptr  
{  
    char a ;   
    short b ;   
    int  c ;   
    double d ;  
};  
#pragma pack()  
int main(void)  
{  
    struct ptr Pt ;  
    struct ptr *pt ;
    printf("ptr:%d\n",sizeof(struct ptr));//16  
    //获取结构体的首地址 
    printf("ptr:%p\n",&Pt); //0028FEA8
    Pt.a = 'a';
    Pt.b = 2 ;
    Pt.c = 4 ;
    Pt.d = 12.04 ;
    //通过container of获取结构体的首地址 
    pt = container_of(&Pt.c, struct ptr , c);
    printf("pt:%p\n",pt);  //0028FEA8
    printf("a:%c\n",pt->a) ;  //'a'
    printf("b:%d\n",pt->b) ;  //2
    printf("c:%d\n",pt->c) ;  //4
    printf("d:%.2lf\n",pt->d);//12.04
    return 0 ;  
}  

linux 内核宏container_of(ptr, type, member)

通过计算member的地址,获取 ptr 所在的结构体type的首地址。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define container_of(ptr, type, member) ({  \         
const typeof(((type *)0)->member) *__mptr = (ptr);\         
(type *)((char *)__mptr - offsetof(type,member));})

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

typeof 获取成员类型

const typeof( ((type *)0)->member ) *__mptr = (ptr); 将ptr 赋值给 __mptr,如果ptr的类型和member指针的类型不一致,这个赋值会有警告,这个是代码严谨性的体现。

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 成员member 在结构体TYPE中的相对地址

ptr - offset 获取ptr所在的结构体的地址。

嵌入式Linux与物联网软件开发:C语言内核深度解析

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022/01/29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
container_of宏定义作用_宏内核
上一篇我们讲到内核链表和普通链表的区别,就有小伙伴追问:内核链表是怎么通过指针域来访问数据域的呢?这篇文章我们就来解答这个问题。
全栈程序员站长
2022/09/23
1.3K0
offsetof()和container_of()函数
在linux 内核编程中,会经常见到一个宏函数container_of(ptr,type,member), 但是当你通过追踪源码时,像我们这样的一般人就会绝望了(这一堆都是什么呀?函数还可以这样定义???怎么还有0呢??? 哎,算了,还是放弃吧。。。)。这就是内核大佬们厉害的地方,随便两行代码就让我们怀疑人生,凡是都需要一个过程,慢慢来吧。
用户6280468
2022/04/18
3230
offsetof()和container_of()函数
Linux内核中container_of宏的详细解释
  我们可以看到,结构体的地址和结构体第一个成员的地址是相同的。这也就是我们之前在拒绝造轮子!如何移植并使用Linux内核的通用链表(附完整代码实现)中提到的为什么在结构体中要把 struct list_head放在首位。
嵌入式与Linux那些事
2021/05/20
1.3K0
Linux内核中container_of宏的详细解释
【Linux API 揭秘】container_of函数详解
container_of可以说是内核中使用最为频繁的一个函数了,简单来说,它的主要作用就是根据我们结构体中的已知的成员变量的地址,来寻求该结构体的首地址,直接看图,更容易理解。
董哥聊技术
2023/12/15
4100
【Linux API 揭秘】container_of函数详解
contain_of宏定义
 Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。 实现方式:   container_of(ptr, type, member) ;    其实它的语法很简单,只是一些指针的灵活应用,它分两步:     第一步,首先定义一个临时的数据类型(通过typeof( ((type *)0)->member )获得)与ptr相同的指针变量__mptr,然后用它来保存ptr的值。  
233333
2018/03/07
1.1K0
container_of宏定义分析
其作用是:已知某结构体的成员member和指向该成员的指针ptr(也就是member的地址),算出该结构体的起始地址。
知否知否应是绿肥红瘦
2025/02/19
830
container_of宏定义分析
C语言 | offsetof宏和container_of宏
今天分享C语言中的两个宏,这两个宏包含了指针和结构体的知识,非常具有代表性。另外,这个题目曾经是大疆无人机的一道笔试题,可见,这两个宏对C语言基础还是有一定要求的。先说明一下,今天所有的例子都是以32位系统来说的。
飞哥
2020/07/10
2.2K0
C语言 | offsetof宏和container_of宏
Linux内核中container_of函数详解
在Linux 内核中,container_of 函数使用非常广,例如 Linux内核链表 list_head、工作队列work_struct中 在Linux 内核中有一个大名鼎鼎的宏container
小小科
2018/05/04
2.2K0
Linux内核中container_of函数详解
002 Linux内核中双向链表的经典实现
本文对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法。其中,也会涉及到Linux内核中非常常用的两个经典宏定义offsetof和container_of。内容包括: 1.Linux中的两个经典宏定义 2.Linux中双向链表的经典实现
范蠡
2019/07/10
1.8K0
002 Linux内核中双向链表的经典实现
剖析c语言结构体的高级用法(二)
昨天分享了结构体里面的一些常见用法(因为测试代码测试的有点晚,有些地方没有分享完。),今天我们来继续分享结构体里面的其他用法。
用户6280468
2022/03/21
5080
剖析c语言结构体的高级用法(二)
offset宏定义_vba offset 用法
函数作用:计算结构体成员的偏移,有些自有代码里也会手写这样的代码,实际上这个函数是标准实现的。实际上如果我们浏览 ANSI C 编译器的标头文件,将在 stddef.h 中遇到这样奇怪的宏。这个红具有可怕的声明。此外,如果您查阅编译器手册,您会发现一个无益的解释,上面写着如下:
全栈程序员站长
2022/09/23
6050
【典藏】大佬们都在用的结构体进阶小技巧
今天跟大家分享一首华晨宇的《我管你》,个人觉得这首歌表达了一种年轻人的热血感,每次听都让自己非常来劲。最近工作挺忙的,写文章或许已经成为了一种兴趣和爱好了吧,也希望每次作者的唠叨都能带给各位小伙伴一些小小的收获。
C语言与CPP编程
2020/12/02
3130
【典藏】大佬们都在用的结构体进阶小技巧
Linux内核list/hlist解读
Linux内核实现了一批优雅而功能强大的双向循环列表操作宏,它们位于/usr/include/linux/list.h(请注意直接#include会报编译错误),这些宏可以直接扣出来,在需要时使用。
一见
2018/08/10
1.3K0
Linux内核list/hlist解读
13张图让你更进一步理解内核进程列表
大家好,我是程栩,一个专注于性能的大厂程序员,分享包括但不限于计算机体系结构、性能优化、云原生的知识。
程栩的性能优化笔记
2023/11/01
3130
13张图让你更进一步理解内核进程列表
工作当中非常实用的Linux内核链表
在上期文章中,已经给大家分享过offsetof()和container_of两个宏函数,这两个宏函数在Linux内核链表里面有大量的应用,对于我们平时工作写代码有很大的帮助。下面是Linux内核链表的内容分享。
用户6280468
2022/06/09
1.1K0
工作当中非常实用的Linux内核链表
通过结构体成员获得结构体地址
通过结构体的成员获得结构体的地址,摘自kernel的一段宏,为了理解container_of,写了个例子
用户3765803
2019/03/05
2K0
赵晨雨: 从微观角度来看linux内核设计
最近总结出来学习内核有两个大的角度,一种就是从宏观角度来看,总的来说就是顺着抽象,管理,操作来看,这种角度更多的是内核中应用层面的内容,用来理解内核中是怎么运转起来的。第二种就是从内核的最细节部分出发,深入到一个个具体的宏,看看内核设计者在细节部分有着怎么样的巧妙之处,这样也有助于我们夯实C语言基础,也可以学习到GNU C的用法。
Linux阅码场
2019/10/08
7900
赵晨雨: 从微观角度来看linux内核设计
Linux内核第一宏
list_entry()有着内核第一宏的美称,它被设计用来通过结构体成员的指针来返回结构体的指针。现在就让我们通过一步步的分析,来揭开它的神秘面纱,感受内核第一宏设计的精妙之处。
Linux阅码场
2019/09/02
1.5K0
Linux内核第一宏
C指针的这些使用技巧,掌握后立刻提升一个Level
半个月前写的那篇关于指针最底层原理的文章,得到了很多朋友的认可(链接: C语言指针-从底层原理到花式技巧,用图文和代码帮你讲解透彻),特别是对刚学习C语言的小伙伴来说,很容易就从根本上理解指针到底是什么、怎么用,这也让我坚信一句话;用心写出的文章,一定会被读者感受到!在写这篇文章的时候,我列了一个提纲,写到后面的时候,发现已经超过一万字了,但是提纲上还有最后一个主题没有写。如果继续写下去,文章体积就太大了,于是就留下了一个尾巴。
IOT物联网小镇
2021/05/13
5080
C指针的这些使用技巧,掌握后立刻提升一个Level
linux内核数据结构 红黑树
红黑树(Red-Black Tree,RBT)是一种平衡的二叉查找树,前面的红黑树原理与实现这篇文章中详细介绍了红黑树的细节。在Linux的内核源代码中已经给我们实现了一棵红黑树,我们可以方便地拿过来进行使用。本文将参考Linux内核的源码和文档资料,介绍Linux内核中红黑树的实现细节及使用方法。
233333
2021/12/22
1.4K0
相关推荐
container_of宏定义作用_宏内核
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验