根据结构体成员变量的地址得到结构体起始地址_通过结构体成员地址确定结构体地址

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

本文参考《Linux操作系统原理与应用》以及如下博客:
https://blog.csdn.net/this_capslock/article/details/39189947

给定一个结构体定义type,这个结构体中某个成员变量的名字member以及它的地址ptr,如何得到包含此成员变量的结构体的地址?即通过结构体成员的地址获取结构体变量的地址?
为了便于分析,我们给出一个实例来说明

struct father_t {
    int a;
    char *b;
    double c;
}f;

根据C语言对struct类型的存储特性,我们可以画这么一个图示:
这里写图片描述

通过分析图示,我们可以看出,我们只需要把当前知道的成员变量的地址ptr,减去它在结构体当中相对偏移4就的到了结构体的地址(ptr-4)。

一、list_entry宏分析
#define list\_entry(ptr, type, member) \
    ((type \*)( (char \*)(ptr) - (unsigned long)(&((type\*)0)->member))) 

如下图,指针ptr指向结构体type中的成员member;通过指针ptr,返回结构体type的起始地址,也就是list_entry返回指向type类型的指针。
这里写图片描述

分析:

  • ((type *)0)->member把0地址转换为type结构的指针,然后获取该结构中member域的指针,也就是获得了member在type结构中的偏移量
  • (char *)(ptr) 求出的是ptr的绝对地址
  • 二者相减,于是得到type类型结构体的起始地址
二、typeof学习

typeof关键字是C语言中的一个新扩展,这个特性在linux内核中应用非常广泛。

typeof 是自动推导后面 ( ) 里的数据类型,所以 typeof(int *) 直接推导出了 int * 型

这样的话,当遇到一个非常复杂的表达式我们很难推断其类型的时候,typeof 就很有用了。另外有一点要注意:typeof 是 GNU C 标准里特有的扩展,标准的 ISO C 并没有这个关键字,所以在编译的时候不能加任何 ISO 的 C 标准选项( -std=c90 ),否则会报错,此时把 -std=c90 改成 -std=gnu90 即 GNU 的标准即可。

三、代码

首先看看Linus的实现:

#define offsetof(TYPE, MEMBER) ((size\_t) &((TYPE \*)0)->MEMBER) 
/**
 * container_of - 通过结构体的一个成员获取容器结构体的指针
 * @ptr: 指向成员的指针。
 * @type: 成员所嵌入的容器结构体类型。
 * @member: 结构体中的成员名。
 */
#define container\_of(ptr, type, member) ({ 
        const typeof( ((type \*)0)->member ) \*\_\_mptr = (ptr); 
 (type \*)( (char \*)\_\_mptr - offsetof(type,member) );
 }) 

(1)定义一个中间变量__mptr,它等于提供给宏的参数ptr,也就是指向某个成员的指针。这个中间变量的命名意义是:
“__”代表内部使用,内核编程中常常这么做;“m”代表middle。
为了避免对 ptr及prt指向的内容造成破坏,这里不直接使用 ptr 而要多多加一个__mptr。
(2)把__mptr转换成 char *类型,因为offsetof得到的偏移量是以字节为单位。两者相减得到结构体的起始位置,再强制转 换成type类型。

这个宏的作用,就是通过一个容器(结构体)中某个成员的指针得到指向这个容器(结构体)的指针,简单的说就是通过成员 找容器。

这里代码进行验证:

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

如果你需要这些资料,可以戳这里获取

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值