从结构体成员指针反推结构体地址:rt_container_of 宏解析

文章目录

    • `rt_container_of` 宏概述
      • 步骤1:计算成员偏移量
      • 步骤2:将成员指针转换为字节指针
      • 步骤3:计算结构体的地址
      • 步骤4:返回结构体指针
    • 代码示例
      • 宏的内部实现解析

rt_container_of 宏概述

rt_container_of 宏是一个非常实用的宏定义,它通过成员指针反向推导出整个结构体变得非常简洁和高效。这在内核编程和驱动开发中经常出现。
rt_container_of 宏的定义如下:

#define rt_container_of(ptr, type, member) \((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))

该宏的目的是通过给定成员指针 ptr,计算出包含该成员的结构体的指针。现在分步骤分析宏的工作原理。

步骤1:计算成员偏移量

首先,((type *)0) 表示一个类型为 type 的空指针。这实际上是将整数 0 强制转换为指向指定类型结构体的指针。接着,&((type *)0)->member 计算出该结构体成员 member 在结构体中的偏移量。此时,&((type *)0)->member 的作用是通过一个虚拟的零地址计算成员 member 在结构体中的位置。

步骤2:将成员指针转换为字节指针

接下来,宏将 ptr 转换为 char * 类型。这一步是为了按字节来进行地址的计算,因为 char 类型的指针可以进行字节级的地址偏移。

步骤3:计算结构体的地址

然后,通过 ptr 和成员的偏移量,利用 (char *)(ptr) - offset 来计算整个结构体的起始地址。这一步将成员指针向回移动 member 在结构体中的偏移量,从而得到了包含该成员的整个结构体的地址。

步骤4:返回结构体指针

最后,宏将计算出来的地址转换为 type * 类型,得到结构体的指针。

代码示例

假设我们有如下的结构体定义:

// 定义一个结构体
struct example {int x;int y;
};

接下来,我们初始化结构体实例并取得成员 y 的指针:

struct example obj;
obj.x = 100;
obj.y = 200;// 假设我们有一个指向成员 y 的指针
int *p_y = &obj.y;

此时,我们有一个指向成员 y 的指针 p_y,但我们希望根据该指针反推出整个结构体的指针。此时就可以使用 rt_container_of 宏来实现这一功能:

struct example *p_obj;
p_obj = rt_container_of(p_y, struct example, y);

宏的内部实现解析

  1. ((type *)0)0 强制转换为指向 struct example 类型的指针。
  2. &((type *)0)->y 计算出成员 ystruct example 中的偏移量。
  3. (char *)(p_y) 将成员指针 p_y 转换为 char * 类型,便于按字节计算地址。
  4. (char *)(p_y) - offset 通过减去偏移量,回退到结构体的起始地址。
  5. 最后,将计算出的地址转换为 struct example * 类型,得到整个结构体的指针。

至此,我们成功地从 p_y 反推出了结构体 obj 的指针 p_obj

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/69410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dijkstra算法类型题解

dijkstra算法(有权图,无权图): 带权路径长度——当图是带权图时,一条路径上所有边的权值之和,称为该路径的带权路径长度 初始化三个数组,final标记各顶点是否已找到最短路径,dist最…

6.Centos7上部署flask+SQLAlchemy+python+达梦数据库

情况说明 前面已经介绍了window上使用pycharm工具开发项目时,window版的python连接达梦数据库需要的第三方包。 这篇文章讲述,centos7上的python版本连接达梦数据库需要的第三方包。 之前是在windows上安装达梦数据库的客户端,将驱动包安装到windows版本的python中。(开…

国产化创新 守护开放边界网络安全

当今数字化浪潮的席卷下,企业、医院、政府部门等各类机构的信息化建设正以前所未有的速度推进。 在这个数字化转型的关键时期,尤其是在涉及国家核心利益和敏感数据的领域,我们不仅要追求技术的先进性,更要确保安全性和自主可控性…

复原IP地址(力扣93)

有了上一道题分割字符串的基础,这道题理解起来就会容易很多。相同的思想我就不再赘述,在这里我就说明一下此题额外需要注意的点。首先是终止条件如何确定,上一题我们递归到超过字符串长度时,则说明字符串已经分割完毕,…

libtorch的c++,加载*.pth

一、转换模型为TorchScript 前提:python只保存了参数,没存结构 要在C中使用libtorch(PyTorch的C接口),读取和加载通过torch.save保存的模型( torch.save(pdn.state_dict()这种方式,只保存了…

postgresql 游标(cursor)的使用

概述 PostgreSQL游标可以封装查询并对其中每一行记录进行单独处理。当我们想对大量结果集进行分批处理时可以使用游标,因为一次性处理可能造成内存溢出。 另外我们可以定义函数返回游标类型变量,这是函数返回大数据集的有效方式,函数调用者…

Linux 快速对比两个文件的差异值

Linux 快速对比两个文件的差异值(无需排序、直接输出) 在日常开发或数据处理中,若需快速对比两个文本文件中的差异值(仅保留第一个文件中的独有内容),Linux 系统提供了两种高效方法。以下是具体操作及适用…

【Pytorch实战教程】PyTorch中的Dataset用法详解

PyTorch中的Dataset用法详解 在深度学习中,数据是模型训练的基石。PyTorch作为一个强大的深度学习框架,提供了丰富的工具来处理和加载数据。其中,Dataset类是PyTorch中用于处理数据的重要工具之一。本文将详细介绍Dataset的用法,帮助你更好地理解和使用它。 1. 什么是Dat…

python:面向对象之魔法方法

概念:主要是提供一些特殊的功能。 1.__init__方法: 一.不带参数: python中类似__xx__() __init__():初始化对象class Car():def __init__(self):self.color blueself.type suvdef info(self):print(f车的颜色是:{self.color})p…

python两段多线程的例子

记录瞬间 其一 # coding:UTF-8 import os import threading from time import ctimedef loop(loops, list): # list存放着每个线程需要处理的文本文件名print(线程 %d 处理的文件列表 %s \n % (loops 1, list))list_len len(list)for i in range(list_len):f open(list[i…

基于蒙特卡洛思想生成电动汽车充电负荷曲线

本程序基于蒙特卡洛思想生成电动汽车充电负荷曲线,利用第十一届电工杯所提供的数据(充电开始时间,充电电量,充电功率)得到一万台电动汽车充电负荷曲线。蒙特卡洛只是解决问题的一种思想,本程序可为其他利用…

语言月赛 202308【小粉兔做麻辣兔头】题解(AC)

》》》点我查看「视频」详解》》》 [语言月赛 202308] 小粉兔做麻辣兔头 题目描述 粉兔喜欢吃麻辣兔头,麻辣兔头的辣度分为若干级,用数字表示,数字越大,兔头越辣。为了庆祝粉兔专题赛 #1 的顺利举行,粉兔要做一些麻…

C++20导出模块及使用

1.模块声明 .ixx文件为导入模块文件 math_operations.ixx export module math_operations;//模块导出 //导出命名空间 export namespace math_ {//导出命名空间中函数int add(int a, int b);int sub(int a, int b);int mul(int a, int b);int div(int a, int b); } .cppm文件…

使用redis实现 令牌桶算法 漏桶算法

流量控制算法,用于限制请求的速率。 可以应对缓存雪崩 令牌桶算法 核心思想是: 有一个固定容量的桶,里面存放着令牌(token)。每过一定时间(如 1 秒),桶中会自动增加一定数量的令牌…

活动预告 | 解锁 Excel 新境界 —— AI 技术赋能下的数据分析超级引擎!

课程介绍 在 AI 技术的浪潮中,Microsoft Excel 已经焕然一新,它不再仅仅是海量复杂数据的处理中心,更是未来趋势的预测大师。智能 Copilot 副驾驶的加入,让 Excel 如虎添翼,成为每一位数据探索者梦寐以求的超级引擎。在…

在阿里云ECS上一键部署DeepSeek-R1

DeepSeek-R1 是一款开源模型,也提供了 API(接口)调用方式。据 DeepSeek介绍,DeepSeek-R1 后训练阶段大规模使用了强化学习技术,在只有极少标注数据的情况下提升了模型推理能力,该模型性能对标 OpenAl o1 正式版。DeepSeek-R1 推出…

Python分享20个Excel自动化脚本

在数据处理和分析的过程中,Excel文件是我们日常工作中常见的格式。通过Python,我们可以实现对Excel文件的各种自动化操作,提高工作效率。 本文将分享20个实用的Excel自动化脚本,以帮助新手小白更轻松地掌握这些技能。 1. Excel单…

使用requestAnimationFrame减少浏览器重绘

文章目录 介绍使用使用rAF前使用rAF后 介绍 在屏幕中,浏览器通常都以60FPS(1/60 s)每帧更新屏幕,但是当前端绑定了一些高频事件,如鼠标移动,屏幕滚动、触摸滑动等时,在一帧的周期内,…

Android的MQTT客户端实现

在 Android 平台上实现 MQTT 客户端的完整技术方案,涵盖基础实现、安全连接、性能优化和最佳实践: 一、技术选型与依赖配置 推荐库 Eclipse Paho Android Service(官方维护,支持后台运行) gradle 复制 // build.gradl…

SQL LEFT JOIN 详解

SQL LEFT JOIN 详解 引言 在SQL数据库查询中,LEFT JOIN 是一种强大的联接操作符,它允许我们从两个或多个表中检索数据。本文将详细介绍 LEFT JOIN 的概念、用法以及在实际应用中的注意事项。 一、什么是 LEFT JOIN? LEFT JOIN 是一种 SQL 联接操作符,用于返回左表(Lef…