container_of学习笔记
最近在学习c语言宏编程,看到了container_of宏,深入学习了一天,做个笔记留念。
1、看一下书上写的container_of的版本:
#define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(PTR,TYPE,MEMBER) ({ \
const typeof(((TYPE *))->MEMBER) *__mptr=(PTR); \
(TYPE *) ((char *)__mptr - offsetof(TYPE,MEMBER)); })
2、举一个实例:
int main(int argc, char *argv[])
{
struct test{
int num;
char ch;
}t1={,'c'};
char *pch=&t1.ch;
struct test *ptt=container_of(pch,struct test,ch);
printf("num=%d\n",ptt->num); return ;
}
替换后的结果:
int main(int argc, char *argv[])
{
struct test{
int num;
char ch;
}t1={,'c'};
char *pch=&t1.ch;
struct test *ptt=({ const typeof(((struct test *))->ch) *__ptmp=(pch); (struct test *)((char *)__ptmp - ((size_t) &((struct test *))->ch)); });
printf("num=%d\n",ptt->num); return ;
}
如果替换后的结果你还能看懂,说明你是真明白了,呵呵,有没有兴趣自己写一遍替换后的代码?
3、多余的不说了,网上有的是讲解的,这里就说二点:
1、container_of宏第一步是做类型检查的,也就是检查ptr是否是指向结构成员member的,如果我们用typeof求出来的类型和ptr不一致,那么编译器会报错。为啥要做这个检查呢?因为ptr和member都是人工输入的参数,宏要保证它们是结构体成员和其相关联的指针,这个宏才有意义,所以类型检查是必须的。
2、第二步相减时,把mptr指针强转成(char *)是因为,char指针减法只移一个字节,如果这样才可能得出准确的地址,否则,改为int类型,在减1就移动4个就乱了。
4、我有研究了最新4.12kernel的该宏,发现有了变化:
/**
* 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 *))->member) && \
!__same_type(*(ptr), void), \
"pointer type mismatch in container_of()"); \
((type *)(__mptr - offsetof(type, member)));
哇,这里有出现一个新宏:__same_type,赶紧用ctags查一下定义,在include/linux/compiler.h中:
/* Are two types/vars the same type (ignoring qualifiers)? */
#ifndef __same_type
# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#endi
有2个新变化,显得更加高大上了,第一,用void *取代了char *来做减法,第二,用__same_type宏来做类型检测,显得更加的直观明了,错了还可以有提示。
container_of学习笔记的更多相关文章
- AM335x(TQ335x)学习笔记——触摸屏驱动编写
前面几篇文章已经通过配置DTS的方式完成了多个驱动的移植,接下来我们解决TQ335x的触摸驱动问题.由于种种原因,TQ335x的触摸屏驱动是以模块方式提供的,且Linux官方内核中也没有带该触摸屏的驱 ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
随机推荐
- Linux下Apache、PHP、MySQL默认安装路径
Apache: 如果采用RPM包安装,安装路径应在 /etc/httpd 目录下 Apache配置文件:/etc/httpd/conf/httpd.conf Apache模块路径:/usr/sbin/ ...
- TQuery
TQuery uses syndb 查询 function Tfmain.query(const sql: string): RawUTF8;var q: TQuery;begin q := TQue ...
- Oracle session active 和 inactive 状态 说明
Oracle session active 和 inactive 状态 说明 原创 2011年06月12日 13:08:00 标签: session / oracle / database / ser ...
- etcd,Docker问题汇总
单节点etcd publish error 正在愉快的进行jenkins流程,突然发现etcd连接不上去了.重新reboot后发现日志publish error Oct :: k8s-master e ...
- 性能工具TProfiler介绍文档
工具介绍 TProfiler是一个可以在生产环境长期使用的性能分析工具.它同时支持剖析和采样两种方式,记录方法执行的时间和次数,生成方法热点 对象创建热点 线程状态分析等数据,为查找系统性能瓶颈提供数 ...
- SEO之巴莱多定律
SEO这个词在2007.2008年好像特别的火,尤其在2007年下半年至今,众多SEO爱好者发起了最大的一轮搜索引擎优化研究风暴,甚至最终逼迫百度等大型搜索引擎公司改变算法. SEO,确实能带来一些经 ...
- go语言基础之基础数据类型 bool类型 浮点型
1.bool类型 示例1: package main import "fmt" func main() { var a bool a = true fmt.Println(&quo ...
- Ubuntu上安装samba不能安装的问题,“下列的软件包有不能满足的依赖关系”
前阵子,雨林木风版ubuntu下安装samba的问题,现在写出来分享一下. root@ubuntu:~# apt-get install samba正在读取软件包列表... 完成正在分析软件包的依赖关 ...
- [Python爬虫] 之九:Selenium +phantomjs抓取活动行中会议活动(单线程抓取)
思路是这样的,给一系列关键字:互联网电视:智能电视:数字:影音:家庭娱乐:节目:视听:版权:数据等.在活动行网站搜索页(http://www.huodongxing.com/search?city=% ...
- Spring Security实现后台管理员登录(一)
一.实现功能 二.数据表设计 为了测试方便,这里创建一个简单的数据表,只含有name和password两个字段.至于角色,权限等,这里都先不考虑. 插入一条数据,name为admin,password ...