c语言container理解

最近看到一个宏定义如下:

/**
 * rt_container_of - return the member address of ptr, if the type of ptr is the
 * struct type.
 */
#define rt_container_of(ptr, type, member) \
    ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))

因为程序中多次使用,所以对其进行了详细分析,过程如下:

这个宏的作用就是通过一个结构体的某个成员的指针,反推出这个结构体的首地址。这种操作非常有用,尤其在C语言中写面向对象的程序时,相当模拟了C++多态的效果。先写个小程序做个实验,验证一下(&((type *)0)->member)到底是什么结果:

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

    char a;
    char b;
    char c;
    char d;
}test_t;

void main(void)
{
    printf("offsetof: %d\n", offsetof(test_t, a));
    printf("offsetof: %d\n", offsetof(test_t, b));
    printf("offsetof: %d\n", offsetof(test_t, c));
    printf("offsetof: %d\n", offsetof(test_t, d));
}

当把结构体成员类型换一下,如下:
typedef struct { 
    int a;
    int b;
    int c;
    int d;
}test_t;

现在我们可以知道(&((type *)0)->member) 这种操作,就是返回member在type这种类型结构体中的相对地址偏移,注意是相对偏移而不是成员在内存中的地址。理解了以上内容后再看offsetof(),它的作用是获取结构体中某个成员相对于该结构体首元素地址的偏移量。test_t 对象内存布局:

从图中可以看出,只要获得了某个成员的地址,再减去这个成员在结构体中的偏移就到到顶了,即反推出了结构体的地址。再理解rt_container_of这个宏定义就是(char *)(ptr)强转换以将移动步进控制为字节,ptr地址减掉这个偏移,就回到结构体首地址了。 

linux中有同样的定义如下:#define container_of(ptr, type, member) ({            \
    const typeof(((type *)0)->member) * __mptr = (ptr);    \
    (type *)((char *)__mptr - offsetof(type, member)); })。这里面还出现了一个typeof关键字.那么,typeof(((type *)0)->member), (&((type *)0)->member) 到底是什么样的一种操作了?ANSI C标准允许值为0的常量被强制转换成任何一种类型的指针,并且转换的结果是个NULL,因此((type *)0)的结果就是一个类型为type *的NULL指针.如果利用这个NULL指针来访问type的成员当然是非法的,但typeof( ((type *)0)->member )是想取该成员的类型,所有编译器不会生成访问type成员的代码,类似的代码&( ((type *)0)->member )在最前面有个取地址符&,它的意图是想取member的相对于type类型首地址的偏移,所以编译器同样会优化为直接取地址。

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

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

相关文章

微信小程序(四十四)鉴权组件插槽-登入检测

注释很详细,直接上代码 新增内容: 1.鉴权组件插槽的用法 2.登入检测示范 源码: app.json {"usingComponents": {"auth":"/components/auth/auth"} }app.js App({globalData:{//定义全局变量isLoad:false} })…

【动态规划】【数学】【C++算法】1449. 数位成本和为目标值的最大数字

作者推荐 【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目 本文涉及知识点 动态规划汇总 LeetCode1449. 数位成本和为目标值的最大数字 给你一个整数数组 cost 和一个整数 target 。请你返回满足如下规则可以得到的 最大 整数: 给当前结果添加…

文件包含知识点详细总结

如果想看图片和观感更好的话,可以直接去我的github或者gitbook github:https://github.com/kakaandhanhan/cybersecurity_knowledge_book-gitbook.22kaka.fun gitbook:http://22kaka.fun description: 这里将通过参考文章和做题一起进行总结,并且文件包含漏洞,很多都利用了…

【Linux】进程概念(冯诺依曼体系结构、操作系统、进程)-- 详解

一、冯诺依曼体系结构 1、概念 (1)什么是冯诺伊曼体系结构? 数学家冯诺伊曼于 1946 年提出存储程序原理,把程序本身当作数据来对待,程序和该程序处理的数据用同样的方式储存。 冯诺伊曼理论的要点是:计算…

【COMP337 LEC1】

Data Preprocessing Phase 数据预处理 1. Feature extraction 特征提取 1. An object is described by a collection of attributes 一个对象可以由一组特征来描述 2. A feature is a property or a characteristic of an objects 物体的属性 2. Data cleaning 数据清洗 Extra…

【EAI 019】Eureka: Human-Level Reward Design via Coding LLM

论文标题:Eureka: Human-Level Reward Design via Coding Large Language Models 论文作者:Yecheng Jason Ma, William Liang, Guanzhi Wang, De-An Huang, Osbert Bastani, Dinesh Jayaraman, Yuke Zhu, Linxi Fan, Anima Anandkumar 作者单位&#xff…

【ES6】Promise

Promise 回调地狱 const fs require(fs);fs.readFile(./a.txt, utf-8, (err, data) > {if(err) throw err;console.log(data);fs.readFile(./b.txt, utf-8, (err, data) > {if(err) throw err;console.log(data);fs.readFile(./c.txt, utf-8, (err, data) > {if(er…

pm2启动的node项目访问不了,npm start却可以访问

netstat -ntlp输入该命令,查看启动的服务端口是否有被监听到,如3001,4000之类的,是node项目启动时候自己配的那个, 若没有,则执行 pm2 delete [app-id/app-name] 先删除启动的这个项目 例如pm2 delete my…

第三百二十二回

文章目录 1. 概念介绍2. 使用方法2.1 基本用法2.2 缓冲原理 3. 示例代码4. 内容总结 我们在上一章回中介绍了"FadeInImage组件"相关的内容,本章回中将介绍CachedNetworkImage组件.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…

《Java 简易速速上手小册》第7章:Java 网络编程(2024 最新版)

文章目录 7.1 网络基础和 Java 中的网络 - 揭开神秘的面纱7.1.1 基础知识7.1.2 重点案例:实现一个简单的聊天程序7.1.3 拓展案例 1:使用 UDP 进行消息广播7.1.4 拓展案例 2:建立一个简单的 Web 服务器 7.2 创建客户端和服务器 - 构建沟通的桥…

Netty源码系列 之 FastThreadLocal源码

目录 Netty优化方案之 FastThreadLocal 前言 ThreadLocal ThreadLocal是干什么的? 为什么要使用ThreadLocal工具类去操控存取目标数据到Thread线程 ? ThreadLocal的使用场景 目标数据存储到Thread线程对象的哪里? 怎么样把一个目标数据…

学习Android的第六天

目录 Android TextView 文本框 TextView 基础属性 范例 带阴影的TextView 范例 带边框的TextView 范例 带图片(drawableXxx)的TextView 范例1 范例2 使用autoLink属性识别链接类型 范例 TextView 显示简单的 HTML 范例1 范例2 SpannableString & Spannable…

政安晨:演绎在KerasCV中使用Stable Diffusion进行高性能图像生成

小伙伴们好,咱们今天演绎一个使用KerasCV的StableDiffusion模型生成新的图像的示例。 考虑计算机性能的因素,这次咱们在Colab上进行,Colab您可以理解为在线版的Jupyter Notebook,还不熟悉Jupyter的的小伙伴可以去看一下我以前的文…

python+ flask+MySQL旅游数据可视化81319-计算机毕业设计项目选题推荐(免费领源码)

摘要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对旅游数据可视化等问题,对旅游数据…

图表自动化开篇

目录 前言: 使用 Canvas 或者 SVG 渲染 选择哪种渲染器 代码触发 ECharts 中组件的行为 前言: 图表自动化一直以来是自动化测试中的痛点,也是难点,痛点在于目前越来越多公司开始构建自己的BI报表平台但是没有合适的自动化测试…

BLE蓝牙安全机制

1. 蓝牙配对 蓝牙配对是建立安全连接的关键过程。对于传统蓝牙应采用SSP配对方式,而低功耗蓝牙4.0和4.1的版本应使用legacy pairing配对方式,4.2以后的版本应采用Secure connection的配对方式。 传统的蓝牙采用的配对方式如下: 蓝牙2.1版本…

《Linux 简易速速上手小册》第4章: 包管理与软件安装(2024 最新版)

文章目录 4.1 包管理基础4.1.1 重点基础知识4.1.2 重点案例:在 Ubuntu 上安装和管理软件4.1.3 拓展案例 1:添加软件仓库4.1.4 拓展案例 2:回滚软件到旧版本 4.2 使用 APT 与 YUM4.2.1 重点基础知识4.2.2 重点案例:在 Ubuntu 上配置…

Kong 负载均衡

负载均衡是一种将API请求流量分发到多个上游服务的方法。负载均衡可以提高整个系统的响应速度,通过防止单个资源过载而减少故障。 在以下示例中,您将使用部署在两台不同服务器或上游目标上的应用程序。Kong网关需要在这两台服务器之间进行负载均衡&…

嵌入式Qt 计算器界面设计

一.计算器界面设计 计算机界面程序分析&#xff1a; 需要用到的组件&#xff1a; 界面设计&#xff1a; 界面设计实现&#xff1a; 实验1&#xff1a;计算器界面设计 #include <QtGui/QApplication> #include <QWidget> //主窗口 #include <QLineEdit> //文…

2024年2月5日-2月11日周报

论文阅读 1. 本周计划2. 完成情况2.1 论文摘要2.2 网络结构2.3 损失函数2.4 优化器2.5 代码2.5.1 代码结果2.5.2 代码大致流程 4. 总结及收获4. 下周计划 1. 本周计划 阅读论文《Data-Driven Seismic Waveform Inversion: A Study on the Robustness and Generalization》并实…