使用container_of宏进行类型转换

简介: 使用container_of宏进行类型转换

使用container_of宏进行类型转换


在C语言编程中,经常会遇到需要在数据结构中找到结构体成员所在的结构体的情况,这时候就可以使用Linux内核中的container_of宏。本文将详细介绍container_of宏的作用、原理及在实际编程中的应用。


基本概念

container_of宏是Linux内核中的一个非常有用的宏,用于在已知结构体成员的情况下,获取包含该成员的完整结构体的指针。它是通过计算结构体成员在结构体中的偏移量来实现的。

宏定义

container_of宏的定义如下:

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

参数解析

  • ptr: 指向结构体中某个成员的指针。
  • type: 结构体的类型。
  • member: 结构体中的成员名称。

原理解析

container_of宏的原理如下:

  1. typeof( ((type *)0)->member ): 通过0指针取得结构体成员的类型。
  2. __mptr: 将ptr转换为member成员的指针。
  3. (char *)__mptr - offsetof(type, member): 计算结构体起始地址和member成员地址的偏移量。
  4. 最终返回整个结构体的指针。

示例代码

让我们通过一个示例来展示如何使用container_of宏来进行类型转换。假设我们有一个结构体定义如下:

#include <stdio.h>
#include <stddef.h> // 包含 offsetof 宏的头文件
// 假设的结构体定义
struct student {
    int id;
    char name[20];
    float score;
};
// 假设的全局变量
struct student stu = {
    .id = 123,
    .name = "John Doe",
    .score = 85.5
};
// 假设的回调函数
void print_student_info(void *ptr) {
    struct student *stu_ptr = container_of(ptr, struct student, score);
    printf("Student ID: %d\n", stu_ptr->id);
    printf("Student Name: %s\n", stu_ptr->name);
    printf("Student Score: %.1f\n", stu_ptr->score);
}
int main() {
    printf("Printing student info using container_of macro:\n");
    print_student_info(&stu.score);
    return 0;
}

*使用cn.juwatech.包名的Java示例

虽然container_of宏主要用于C语言中,Java中并没有类似的需求和宏定义机制。因此,在Java代码示例中,我们可以通过cn.juwatech.*包名来展示实际的应用场景,如Java中的包管理和类定义。然而,对于container_of宏这类特定于C语言的技术,Java通常会采用不同的方法来解决相似的问题,例如通过接口、继承和泛型等方式来管理和操作数据结构。

总结

本文详细介绍了container_of宏的定义、原理及在实际编程中的应用。通过使用这个宏,我们可以方便地在已知结构体成员的情况下,获取包含该成员的完整结构体的指针,从而实现更加灵活和高效的数据结构管理和操作。

相关文章
|
2月前
|
编译器 C语言
C语言宏定义(#define定义常量​、#define定义宏​、 带有副作用的宏参数、 宏替换的规则、 宏函数的对比)
C语言宏定义(#define定义常量​、#define定义宏​、 带有副作用的宏参数、 宏替换的规则、 宏函数的对比)
|
2月前
|
编译器
关键字static#define 定义常量和宏
关键字static#define 定义常量和宏
24 0
|
2月前
|
Rust 编译器 开发者
Rust中的进阶宏:派生宏与属性宏
本文将深入探讨Rust编程语言中的派生宏(Derive Macros)和属性宏(Attribute Macros)这两种进阶宏的用法。派生宏用于自动生成实现特定trait的代码,而属性宏则允许我们为模块、函数、结构体等添加自定义属性。我们将通过实例展示如何在Rust项目中使用这些高级宏来增强代码的可读性和可维护性。
|
2月前
#define定义常量和宏
#define定义常量和宏
16 0
|
2月前
|
Linux
offsetof宏与container_of宏
offsetof宏与container_of宏
19 0
|
10月前
|
编译器
#define 定义常量和宏
工作机理:直接替换,以下列代码为例编译器直接将用到max的地方替换为100
41 0
|
12月前
|
存储 安全 算法
02-📝C++核心语法|C++对C的扩展【::作用域运算符、名字控制、struct类型加强、C/C++中的const、引用(reference)、函数】
复习`C++核心语法`,且适当进行汇编探索底层实现原理,进一步夯实基础,为以后的`底层开发`、`音视频开发`、`跨平台开发`、`算法`等方向的进一步学习埋下伏笔。
02-📝C++核心语法|C++对C的扩展【::作用域运算符、名字控制、struct类型加强、C/C++中的const、引用(reference)、函数】
|
存储 C语言
【学习笔记之我要C】初识常见关键字、#define定义常量和宏
【学习笔记之我要C】初识常见关键字、#define定义常量和宏
89 0
【学习笔记之我要C】初识常见关键字、#define定义常量和宏
|
存储 自然语言处理 安全
【C++】C++入门 --- 命名空间 | 输入输出 | 缺省函数 | 函数重载 | 引用 | 内联函数 | auto关键字 | 基于范围的for循环 | 指针空值
命名空间 | 输入输出 | 缺省函数 | 函数重载 | 引用 | 内联函数 | auto关键字 | 基于范围的for循环 | nullptr
148 0
【C++】C++入门 --- 命名空间 | 输入输出 | 缺省函数 | 函数重载 | 引用 | 内联函数 | auto关键字 | 基于范围的for循环 | 指针空值
宏#define的三种基本定义方式:固定值,表达式,运算符。
宏#define的三种基本定义方式:固定值,表达式,运算符。
 宏#define的三种基本定义方式:固定值,表达式,运算符。

热门文章

最新文章