首先,今天看到代码,接触到这个宏定义,所以有意去研究了一下:
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
以上面例子来说这个宏的作用为:根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针
/**
* container_of - cast a member of a structure out to the containingstructure
* @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) );})
以上参数英文的,相信能够写代码的童鞋都能看得懂的吧。下面针对这个宏我做下详细的介绍:
1.宏的最外围是 ({}) ,这个结构的作用举个例子:
intx=({7;1;})+2;
printf("%d\n",x);
输出的值为3,意思就是这个结构会找出最后一个定义的值来做运算,说的够直白吧?
2.宏的内部有一个typeof,这个作用就是为了申明一个类型,((type *)0)将零转化为type(这里的type是一个结构体类型)的指针类型,指向我们的结构体成员member,就是以零地址开始开始指向member。
3.那么我想问一下大家&((type *)0)->member是否可以说是member在整个结构体中的偏移量?ok,那么我就就仅仅认为((type *)0)->member仅仅只一个member类型的数据,typeof( ((type *)0)->member ) *__mptr就是说定义一个member数据类型的指针变量__mptr,等于指向member的指针变量。
4.(type *)( (char *)__mptr - offsetof(type,member) ),咋一看,offsetof不知道什么意思,ok
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
什么意思呢?这不就是我们刚才分析的吗?返回member的偏移量嘛,不解释!看不懂的自己把第三点再看一遍,然后告诉我你懂了!
5.那么前面的 (type *)( (char *)__mptr - offsetof(type,member) )整体看上去一些小伙伴还是看着吃力,有木有?ok,(char *)__mptr将__mptr转换为字符型指针,原来指向member的,减去它的偏移量,那么就得到它原本所在结构的首地址。那么回到
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
该hid设备不就是为了得到hid_device的首地址 ({}) 定义的最后一个就是其返回的值,那么就是首地址。