linux中offsetof与container_of宏定义

linux内核中offsetof与container_of的宏定义

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

/** 
* container_of - cast a member of a structure out to the containing structure 
* @ptr:        the pointer to the member. 
* @type:       the type of the container struct this is embedded in. 
* @member:     the name of the member within the struct. 
* */

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

offsetof含义:获取结构体中某个成员变量相对于结构体首地址的内存位置偏移;

container_of含义:根据结构体中某个成员变量的内存地址获取结构体的内存首地址。

offsetof宏详解:

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

1)、参数TYPE为结构体的类型定义,MEMBER为结构体成员变量名称;

2)、实现方法比较取巧:将0强制转化TYPE类型的指针,然后对MEMBER变量取址;

3)、代码示例:

typedef struct

{

  int a;

  char b;

  void *c;

} off_struct_s;

printf("offset a:%d b:%d c:%d\n", offsetof(off_strcut_s, a), offsetof(off_strcut_s, b), offsetof(off_strcut_s, c));

最终结果为:offset a:0 b:4 c:8

container_of宏详解:

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

1)、参数ptr为结构体成员的内存地址,type为结构体类型定义,member为结构体成员变量名称;

2)、typeof为gun编译器系列的内置函数,函数返回当前变量的类型;

3)、const typeof( ((type *)0)->member ) *__mptr = (ptr); 这行定义了一个member类型的指针变量__mptr,并且值初始化为ptr(注意:这里type也是0强制转换);

4)、(type *)( (char *)__mptr - offsetof(type,member) );

这行则是将结构体成员变量的内存地址减去此成员变量与结构体首地址的偏移(offsetof前面已讲解),即为结构体的内存首地址;

5)、代码示例:

off_struct_s stru;

void *ptr;

ptr = (void *)(container_of(&stru.c, off_struct_s, c));

printf("stru_addr:%p container_addr:%p\n", &stru, ptr);

运行结果必然是&stru与ptr的内存地址是一样的,这个例子只是做一个证明,实际使用时肯定是先不知道结构体首地址的,需要由结构体变量地址计算结构体首地址。

其实总结起来很简单,要想根据一个结构体变量的指针计算出结构体本身的指针,只需要当前变量指针减去变量到结构体首的偏移(base = ptr - offset)。

时间: 2024-08-29 09:46:28

linux中offsetof与container_of宏定义的相关文章

(六)linux内核中的offsetof与container_of宏

参考: offsetof与container_of宏[总结] #define offsetof(type, member) (size_t)&(((type*)0)->member) #define container_of(ptr, type, member) ({ const typeof( ((type *)0)->member ) *__mptr = (ptr); (type *)( (char *)__mptr - offsetof(type,member) );}) 原文地

VC中预处理指令与宏定义详解

刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个经典的例子 使用预处理与宏定义最经典的例子莫过于加在一个头文件中以避免头文件被两次编译.试想这种的情况,有一个文件headerfile.h 它被包含在headerfile1.h中,同时在headerfile2.h 中也被包含了,现在有一个CPP文件,implement.cpp 包含了headerfi

swift中 类似OC的宏定义

OC 中调试打印 /** *  自定义Log */ #ifdef DEBUG #define JYLog(...)        NSLog(__VA_ARGS__) #else #define JYLog(...) #endif // swift中我写了这么一个类,进行调试输出 调用方法  Debug.Log(error) import UIKit class Debug: NSObject{ // TODO: 为调试修改 private static let debug = true cla

container_of宏定义解析

container_of宏,定义kernel.h中: /** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within th

offsetof与container_of宏分析

offsetof宏:结构体成员相对结构体的偏移位置 container_of:根据结构体成员的地址来获取结构体的地址 offsetof 宏 原型: #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER) (TYPE *)0非常巧妙,告诉编译器有一个指向结构体 TYPE 的指针,其地址是0,然后取该指针的 MEMBER 地址 &((TYPE *)0)->MEMBER,因为基址是0,所以这时获取到的 MEMBER

C中的预编译宏定义

文章来自 http://www.uml.org.cn/c++/200902104.asp 在将一个C源程序转换为可执行程序的过程中, 编译预处理是最初的步骤. 这一步骤是由预处理器(preprocessor)来完成的. 在源流程序被编译器处理之前, 预处理器首先对源程序中的"宏(macro)"进行处理. C初学者可能对预处理器没什么概念, 这是情有可原的: 一般的C编译器都将预处理, 汇编, 编译, 连接过程集成到一起了. 编译预处理往往在后台运行. 在有的C编译器中, 这些过程统统由

对offsetof、 container_of宏和结构体的理解

offsetof 宏 #include<stdio.h> #define offsetoff(type, member)      ((int)&((type*)0)->member) /* ((type*)0)->member 释义:声明一个相应类型的结构体指针,该指针指向0地址处.再通过该指针访问各元素.我们只要获取一个指针就能访问其内部的元素吗,可以这么搞?其实我是想联系全局和非全局变量,通过上面这个代码也许你不明白我要表达的意思.请继续慢慢看,直到本文后面,结合本文

内核中likely和unlikely宏定义

在内核代码中经常会看到unlikely和likely的踪影.他们实际上是定义在 linux/compiler.h 中的两个宏. #define likely(x)    __builtin_expect(!!(x), 1) #define unlikely(x)  __builtin_expect(!!(x), 0) 这里的__built_expect()函数是gcc的內建函数. 至于为什么要在内核代码中使用这两个宏,主要的目的是为了进行代码的优化,提高系统执行速度. 比如 : if (like

C中变量名通过宏定义转换成char*类型字符串

#include <iostream> p>define name_to_str(name)(#name) int main() { int sum = 10; std::cout<<name_to_str(sum)<<std::endl;//调用宏输出char*型“sum” system("pause"); return 0; }