之前在剖析内核链表的文章中就有说到这个 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. 详解EBS接口开发之采购订单导入

    采购订单常用标准表简介 1.1   常用标准表 如下表中列出了与采购订单导入相关的表和说明: 表名 说明 其他信息 po.po_headers_all 采购订单头 采购订单号,采购类型,供应商,地点, ...

  2. Swift如何取得View所属的ViewController

    从VC取得View很容易,但有些情况下我们需要从View反向获取VC. 不过在一些特殊的场合,Cocoa库帮我们想的很周到,比如在自定义View过渡动画的时候: func animateTransit ...

  3. Android 网络图片加载之cude 框架

    偶然发现了这个框架,阿里图片加载用的这个框架.非常简单操作步骤. 1.首先下载软件包,直接搜Cube ImageLoader 这个. 2.加入jar文件 3.使用前的配置: public class ...

  4. Android之触摸手势检测GestureDetector使用详解

    在Android中,当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing,onSingleTapConfirmed(单击),onDoubleTap(双击)等等. 一般情 ...

  5. SSH网上商城---商品详情页的制作

    在前面的博文中,小编分别简单的介绍了邮件的发送以及邮件的激活,逛淘宝的小伙伴都有这样的体会,比如在搜索框中输入连衣裙这个商品的时候,会出现多种多样各种款式的连衣裙,连衣裙的信息包括价格,多少人购买,商 ...

  6. Servlet之Response对象

    下面的方法可用于在 Servlet 程序中设置 HTTP 响应报头.这些方法通过HttpServletResponse 对象可用. 1    String encodeRedirectURL(Stri ...

  7. iOS开发之音频播放AVAudioPlayer 类的介绍

    主要提供以下了几种播放音频的方法: 1. System Sound Services System Sound Services是最底层也是最简单的声音播放服务,调用 AudioServicesPla ...

  8. Dynamics CRM 2015Online Update1 new feature之表单页Tabs切换

    CRM2011的界面相对于CRM4.0进行了比较大的改动,N久没见过4.0的界面了所以忘了表单是什么样子的了,但2011的表单中若含有多个tab的话,是可以通过左侧栏进行切换,话说2013的界面相对2 ...

  9. java加载外部文件数据到代码中:外部数据文件放到jar包中,调用方法getResourceAsStream

    任务要将数据文件geo.txt加载进行.因为是别人写的总体项目,不能乱动位置.只能将geo.txt打包到jar中某目录.比如,放到.class文件下怎么加载:http://riddickbryant. ...

  10. 控件之combox

    一. combox显示     首先combox有两个属性来存储数据:DisplayMember(显示成员),ValueMember(值成员) ,DisplayMember是我们在combox界面上看 ...