之前在剖析内核链表的文章中就有说到这个 container_of宏展开后的应用技巧。

//offset(struct list , list);----->展开后((size_t) & (struct list *)0 -> list)
//写清楚一点时这样:
//struct list *p = NULL ; &p->list ; 即是求p这个结构体指针的成员list的地址,只不过p是0
//地址,从0地址开始计算list成员的地址,也就是成员list在结构体struct list中的偏移量
//这个宏的作用就是求解MEMBER成员在TYPE中的偏移量
//编译器不报错的原因是在编译阶段就已经知道结构体里每个成员的属性的相对偏移量了 ,
//在代码中对结构体成员的访问其实最终 会被编译器转化为对其相对地址的访问
//在代码运行期间,其实根本就没有变量名还有属性成员,有的也就只有地址。
//container_of最终结果返回的是第二个表达式的值,这里所谓的__mptr是一个中间的指针变量,其实就是list_head指针类型,被初始化为ptr
//而我所说的这个ptr,就是我们要求的list_head中的节点地址,定义这样一个中间的指针变量其实考虑了很多因素
//如果传参进来的是ptr++,会有副作用,就类似于(p++)+(p++)这样
//而(char *)__mptr之所以要强制转换为char实质上是因为地址是以字节为单位的,而char的长度是一个字节
//所以contain_of实质是两个地址相减的结果
//__mptr是结构体中list_head节点的地址,offset宏求的是list_head节点在MEMBER在结构体中TYPE中的偏移量,那么
//__mptr减去它所在结构体中的偏移量,就是结构体的地址了。

上代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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) );})
struct cona_t{
	int i;
	int j;
	int v;
	char t[10];
	unsigned short xy;
};

struct cona_t ct;
unsigned short xy;
int main(int argc,char * argv[])
{
	int xy;
	struct cona_t * p;
	memset(&ct,0,sizeof(struct cona_t));
	ct.i = ct.j = ct.v = 10;
	sprintf(ct.t,"%s","sdf");
	ct.xy = 20;
	p = container_of(&ct.xy,struct cona_t,xy);

	printf("%s\n",p->t);
	return 0;
}

运行结果:

从运行结果可以看出我们可以通过一个结构体指针去获取一个结构体本身的成员。

linux内核 container_ofC语言之应用的更多相关文章

  1. Linux内核--C语言中内嵌汇编 asm __volatile__

    在内嵌汇编中,可以将C语言表达式指定为汇编指令的操作数,而且不用去管如何将C语言表达式的值读入哪个寄存器,以及如何将计算结果写回C 变量,你只要告诉程序中C语言表达式与汇编指令操作数之间的对应关系即可 ...

  2. linux内核学习之一 简单c语言反汇编

    (我是第一次发技术博客的菜鸟,恳请大家指导!!) 一  由简单c程序生成汇编代码 首先给出本次我们要反汇编的简单c语言程序:(够简单吧~) 在linux环境中使用下面的命令条件编译: 生成汇编文件sh ...

  3. Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7)

    http://blog.chinaunix.net/uid-20543672-id-3157283.html Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3 ...

  4. linux内核中的C语言常规算法(前提:你的编译器要支持typeof和type)

    学过C语言的伙伴都知道,曾经比较两个数,输出最大或最小的一个,或者是比较三个数,输出最大或者最小的那个,又或是两个数交换,又或是绝对值等等,其实这些算法在linux内核中通通都有实现,以下的代码是我从 ...

  5. C语言之linux内核实现位数高低位互换

    linux内核实在是博大精深,有很多优秀的算法,我之前在工作中就遇到过位数高低位交换的问题,那时候对于C语言还不是很熟练,想了很久才写出来.最近在看内核的时候看到有内核的工程师实现了这样的算法,和我之 ...

  6. C语言之linux内核实现最大公约数算法

    最大公约数算法,又称欧几里德算法,至今已有几千年的历史了.在我们开始学习C语言的时候最常用的算法就是辗转相除法,其实在linux内核中,内核也是使用这样的方法实现两数最大公约数的计算. 两个整数的最大 ...

  7. 嵌入式C语言自我修养 04:Linux 内核第一宏:container_of

    4.1 typeof 关键字 ANSI C 定义了 sizeof 关键字,用来获取一个变量或数据类型在内存中所占的存储字节数.GNU C 扩展了一个关键字 typeof,用来获取一个变量或表达式的类型 ...

  8. 嵌入式C语言自我修养 01:Linux 内核中的GNU C语言语法扩展

    1.1 Linux 内核驱动中的奇怪语法 大家在看一些 GNU 开源软件,或者阅读 Linux 内核.驱动源码时会发现,在 Linux 内核源码中,有大量的 C 程序看起来“怪怪的”.说它是C语言吧, ...

  9. C 语言代码风格之 Linux 内核代码风格

    GitHub: https://github.com/storagezhang Emai: debugzhang@163.com 华为云社区:https://bbs.huaweicloud.com/b ...

随机推荐

  1. Microsoft公司的匈牙利法命名规则

    Microsoft公司的"匈牙利"法命名规则 比较著名的命名规则当推Microsoft公司的"匈牙利"法,该命名规则的主要思想是"在变量和函数名中加入 ...

  2. TortoiseSVN使用

    TortoiseSVN是Subversion版本控制系统的一个免费开源客户端,不需要为使用它而付费. TortoiseSVN是 Subversion 的 Windows 扩展.它使你避免接触 Subv ...

  3. FFmpeg的HEVC解码器源代码简单分析:解析器(Parser)部分

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

  4. JAVA面向对象-----接口的概述

    接口的概述 **接口(interface):**usb接口,主要是使用来拓展笔记本的功能,那么在java中的接口主要是使用来拓展定义类的功能,可以弥补java中单继承的缺点. class Pencil ...

  5. XMPP系列(六)---创建群组

    最近公司项目需要,要做一个自己的IMSDK,顺便先把之前没有记录的群聊功能记录一下. 先上资料,查看XMPP群聊相关的资料,可以去这里看协议:XEP-0045 . 创建群组 XMPP 框架里有一个类X ...

  6. ORACLE数据库学习之备份与恢复

     oracle数据库的备份与恢复 第一部分:数据库的备份 备份的必要性 因为各种人为或外界的因素可能会造成数据库中灾难性的数据丢失,为了保证数据库中数据的安全,必须采取备份措施保证RDBMS中包含 ...

  7. UNIX网络编程——select函数的并发限制和 poll 函数应用举例

    一.用select实现的并发服务器,能达到的并发数,受两方面限制 1.一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n来调整或者使用setrlimit函数设置,  ...

  8. Android优化之ArrayMap

    ArrayMap的介绍 官方对ArrayMap也有说明:它不是一个适应大数据的数据结构,相比传统的HashMap速度要慢,因为查找方法是二分法,并且当你删除或者添加数据时,会对空间重新调整,在使用大量 ...

  9. Android中R文件的丢失问题以及aapt.exe停止工作如何解决

    出现上面这个错误,说胆你的xml文件中出问题了..找了一下原因.如下.. R.java这个文件是会自动生成的.但是有时候你写错xml文件的时候,R.java是不会自动生成对应的值.这个时候我们会很习惯 ...

  10. Eclipse中查看没有源码的Class文件的方法

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/18798473 本文作者:sushengmiyan 我们在使用Eclipse的时候,经常 ...