c语言函数-containerof()
今天在看ESP32库的源码时,发现了一个神奇的函数:__containerof()
。可以从结构体成员的地址获得该结构体的地址,实现一种类似于找father的方法,故记录。
函数原型
1 |
|
1 |
函数作用
函数实现的功能也很简单,用来已知成员的地址和名称以及该结构体的类型,求该结构体的地址。
分析
该函数的核心步骤是:
1 | type的起始地址 = ptr - size (这里需要都转换为char *,因为它为单位字节) |
其中的核心是size的获得。
1 |
这里使用了0地址的用法。当一个0地址被强转为TYPE结构体的地址,那么它成员的地址就会变成该成员相对于结构体地址的偏移。(TYPE *)0)->MEMBER
指向了成员,(size_t) &((TYPE *)0)->MEMBER
取了这个成员的地址并强转为size_t
。
然后是这一看起来没有用的一行。
1 | const typeof( ((type *)0)->member ) *__mptr = (ptr); |
这一行是用来提供警告的,如果传入的参数参数类型不一样(可能是传错了),这就会产生一个警告,帮助排查错误。
最后,有一个宏函数的返回问题。
1 |
上述函数在最后一句不是一个完整的句子,而只有右值。该右值就会作为返回值返回。