首页 > 编程知识 正文

assert是一个宏,而不是函数,container_of函数

时间:2023-05-06 09:46:02 阅读:115946 作者:4923

这是Linux-source-4.13.0/include/Linux/kernel.h中的container_of )函数的定义。

#definecontainer_of(ptr、type、member ) (void*__mptr=) void* ) ptr ); BUILD_BUG_ON_MSG (! __same_type(*(ptr ),) type * )0)-member ) (! __same_type(*(ptr ),void ),(pointertypemismatchincontainer _ of () ) ); () (type* ) __mptr-offsetof ) type,member ) ); ptr:表示结构中member的地址

type:表示结构体类型

member:代表结构的成员

更多版本如下。

#definecontainer_of(ptr、type、member ) (consttypeof ) ) (type )0)-member ) _ _ mptr=(ptr ); ( (type * ) ) char*__mptr-offsetof ) type,member ); }他们的区别在于__mptr的类型不同,一个是void*,另一个是type *。 其中包括在linux/stddef.h中定义的宏函数,即offsetof (可见也包括函数)

#defineoffsetof(type,MEMBER ) ) size_t ) ) TYPE *)-MEMBER ) ) ) ) )。

首先理解offsetof这个宏函数。 读了很多博客终于理解了。

假设(TYPE * )0 :即虚拟地址0存在,并将地址强制转换为结构指针类型(TYPE * ) 0。 地址0到sizeof[type]-1长度的存储器区域可以视为一个结构的存储器。 0是此虚构结构的起始地址,后跟虚构结构的成员。 这些成员没有实际内容,但他们之间的地址结构与普通赋值结构相同。

使用此虚构结构地址,只需确定成员相对于结构起始地址的偏移量。 选择“0”作为虚拟地址也很方便,因为每个成员所在的虚拟内存地址的位置是偏移量。 当然也可以设定为其他值,但最后进行减法运算才是真正的偏移。

下面的步骤简单说明。

代码清单:

# include stdio.h # define offset of (type,MEMBER ) ) int ) ) TYPE * )0)-MEMBER ) struct unit{char a; 短乙; int c; 双精度d; (; intmain(intargc,char const *argv[] ) {结构单元单元; printf (单元结构所占字节数%d(n ),sizeof )结构单元); int offset1=offset of (结构单元,a ); int offset2=offset of (结构单元,b ); int offset3=offset of (结构单元,c ); int offset4=offset of (结构单元,d ); printf (单元结构成员a的偏移地址为%dn )、offset1); printf (单元结构成员b的偏移地址为%dn )、offset2); printf (单元结构成员c的偏移地址为%dn )、offset3); printf (单元结构成员d的偏移地址为%dn )、offset4); 返回0; }最后输出结果:

由此,也能够推出结构体unit存储器存储的概略结构

char为1字节,short为2字节,int为4字节,double为8字节,null部分不保存内容只是为了实现字节对齐

显示了整个空间占16字节,为什么sizeof (单元)为16。

container_of ) )让我们了解一下函数的实现。

此函数用于根据特定结构的特定成员获取该结构的起始地址。

在所有版本中,第一步是创建新的指针变量__mptr,并将它分配给特定结构成员的地址(ptr )

从该__mptr减去结构成员的偏移量(根据offsetof函数计算的结果)得到的是该具体结构的具体起始地址。 强烈转换为所需的结构类型。

举个例子吧。

代码清单:

# include stdio.h # define offset of (type,MEMBER ) (int ) ) TYPE * )0)-MEMBER ) definecontainer_of1 ) ptr,ttr }#definecontainer_of2(ptr、type、member ) (consttypeof ) ) (type )0)-member ) _ _ mptr=(ptr ); () (type* ) __mptr-offsetof ) type,member ) ); } (结构单元) chara; 短乙; int c; 双精度d; (; intmain(intargc,char const * argv [ ] (结构单元*单元_ by _ container1); 从container_of1函数获取,成员为astruct unit *unit_by_container2; 从container_of2函数获取,成员为astruct unit *unit_by_container3; 从container_of1函数获取,成员为bstruct unit unit_test={'x ',1,2,3.3 }; char *unit_a=unit_test.a; short *unit_b=unit_test.b; int *unit_c=unit_test.c; double *unit_d=unit_test.d; unit _ by _ container1=container _ of1 (unit _ a,struct unit,a ); unit _ by _ container2=container _ of2 (unit _ a,struct unit,a ); unit _ by _ container3=container _ of1 (unit _ b,struct unit,b ); printf(unit_by_container1-b为%un )、unit_by_container1-b ); printf(unit_by_container1-c为%dn ',unit_by_container1-c ); printf(unit_by_container1-d为%fn ',unit_by_container1-d ); printf(unit_by_container2-b为%un ',unit_by_container2-b ); printf(unit_by_container2-c为%dn ',unit_by_container2-c ); printf(unit_by_container2-d为%fn ',unit_by_container2-d ); printf(unit_by_container3-a为%cn ',unit_by_container3-a ); printf(unit_by_container3-c为%dn ',unit_by_container3-c ); printf(unit_by_container3-d为%fn ',unit_by_container3-d ); 返回0; }执行结果:

可以看到前面提到的两个container_of版本达到了相同的效果。

由此,我相信对这两个函数会有很深的理解。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。