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 的地址就是相当于在结构体 TYPE 中的偏移量了。
Example:
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
struct TYPE{
int mem;
int member;
};
int main()
{
struct TYPE type;
printf("&type = %p\n", &type);
printf("&type.member = %p\n", &type.member);
printf("&((struct type *)0)->member = %lu\n", ((size_t)&((struct TYPE *)0)->member) );
printf("offsetof(struct TYPE member) = %zd\n", offsetof(struct TYPE, member));
return 0;
}
/*
result:
&type = 0x7ffc1104a110
&type.member = 0x7ffc1104a114
&((struct type *)0)->member = 4
offsetof(struct TYPE member) = 4
*/
container_of 宏
原型:linux-4.18.5
/**
* 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) ({ \
void *__mptr = (void *)(ptr); \
BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
!__same_type(*(ptr), void), \
"pointer type mismatch in container_of()"); \
((type *)(__mptr - offsetof(type, member))); })
网上所见更多是底下这个版本:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
第一部分:void *__mptr = (void *)(ptr); 或const typeof( ((type *)0)->member ) *__mptr = (ptr);
两个的差别在于 __mptr 的类型一个是 void * ,一个是 type *。
void * 较为容易理解,下面来看看 type *:
关于 typeof 关键字其作用是返回变量的类型,简单理解就是如下,详细可参见GCC typeof在kernel中的使用——C语言的“编译时多态”
int a;
typeof(a) b; //这等同于int b;
typeof(&a) c; //这等同于int* c;
因此const typeof( ((type *)0)->member ) *__mptr = (ptr); 的作用就是通过 typeof 获取结构体成员 member 的类型,然后定义一个这个类型的指针变量 __mptr 并将其赋值为 ptr。
第二部分:(type *)( (char *)__mptr - offsetof(type,member) ),通过offsetof宏计算出 member 在 type 中的偏移,然后用 member 的实际地址__mptr减去偏移,得到 type 的起始地址。从上面关于offsetof宏的 Example 也可以验证这一点:
&type.member = 0x7ffc1104a114 - &((struct type *)0)->member = 4 = &type = 0x7ffc1104a110
offsetof与container_of宏分析的更多相关文章
- 对offsetof、 container_of宏和结构体的理解
offsetof 宏 #include<stdio.h> #define offsetoff(type, member) ((int)&((type*)0)->me ...
- linux中offsetof与container_of宏定义
linux内核中offsetof与container_of的宏定义 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->M ...
- (转)offsetof与container_of宏[总结]
1.前言 今天在看代码时,遇到offsetof和container_of两个宏,觉得很有意思,功能很强大.offsetof是用来判断结构体中成员的偏移位置,container_of宏用来根据成员的地址 ...
- offsetof与container_of宏[总结]
1.前言 今天在看代码时,遇到offsetof和container_of两个宏,觉得很有意思,功能很强大.offsetof是用来判断结构体中成员的偏移位置,container_of宏用来根据成员的地址 ...
- 【转】container_of宏 分析
在学习Linux驱动的过程中,遇到一个宏叫做container_of.该宏定义在include/linux/kernel.h中,首先来贴出它的代码: /** * container_of - cast ...
- container_of宏
title: container_of宏 date: 2019/7/24 15:49:26 toc: true --- container_of宏 解析 在linux链表结构中有这样一个宏,通过成员变 ...
- container_of宏定义分析---linux内核
问题:如何通过结构中的某个变量获取结构本身的指针??? 关于container_of宏定义在[include/linux/kernel.h]中:/*_** container_of - cast a ...
- 内核中container_of宏的详细分析【转】
转自:http://blog.chinaunix.net/uid-30254565-id-5637597.html 内核中container_of宏的详细分析 16年2月28日09:00:37 内核中 ...
- linux内核container_of宏定义分析
看见一个哥们分析container_of很好,转来留给自己看 一.#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMB ...
随机推荐
- C++11 学习笔记
unique_ptr 可以实现如下功能: 1.为动态申请的内存提供异常安全 2.讲动态申请的内存所有权传递给某函数 3.从某个函数返回动态申请内存的所有权 4.在容器中保存指针 5.auto_ptr ...
- hadoop下生成echarts关系图
数据 O700 O2833 O700 O331 O700 O3425 O700 O350 O700 O3516 O700 O3826 读取文件类 public class FileReadFromHd ...
- ES6---new Promise()讲解(尤其注意里面的参数resolve、reject)
直接打印出来看看吧,console.dir(Promise). 这么一看就明白了,Promise是一个构造函数,自己身上有all.reject.resolve这几个眼熟的方法,原型上有then.cat ...
- fabric报错:Fatal error: run() received nonzero return code 1 while executing!
今天在使用fabric远程安装rpm时,一直报:Fatal error: run() received nonzero return code 1 while executing! 这看起来也是没笔病 ...
- AQS源码分析笔记
经过昨晚的培训.对AQS源码的理解有所加强,现在写个小笔记记录一下 同样,还是先写个测试代码,debug走一遍流程, 然后再总结一番即可. 测试代码 import java.util.concurre ...
- 2019春Python程序设计作业2(0326--0401)
1-1 已知st="Hello World!",使用print(st[0:-1])语句可以输出字符串变量st中的所有内容. (2分) T F 1-2 Python程 ...
- Python模块之-OS模块
一.os模块概述 Python os模块包含普遍的操作系统功能.如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的.(一语中的) 二.常用方法 1.os.name 输出字符串指示正在使用的平台 ...
- 关于Struts2_2.3.24中FilterDispatcher过期的问题
今天在使用最新版Struts2.3.24时,总是报出如下警告: ******************************************************************** ...
- Hive分析窗口函数(一) SUM,AVG,MIN,MAX
Hive分析窗口函数(一) SUM,AVG,MIN,MAX Hive分析窗口函数(一) SUM,AVG,MIN,MAX Hive中提供了越来越多的分析函数,用于完成负责的统计分析.抽时间将所有的分析窗 ...
- java后台转json、转对象、转list集合
前台数据传递到后台转json 1.普通格式转换成对象 String data=request.getParameter("data"); //单数据的时候转换方式 JSONObje ...