container_of的用法
1. container_of的用途说明
container_of的主要作用是:通过已知的一个数据结构成员指针ptr,数据结构类型type,以及这个成员指针在这个数据结构中的成员名member,来获取指向这个数据结构的指针type *。
2. offsetof的定义
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
offsetof是一个宏它的主要作用是:获取一个数据结构的成员,在这个数据结构中的偏移。
offsetof()宏函数它接受两个参数:一个是数据结构类型TYPE;另一个是在这个数据结构类型中的成员名。
offsetof获取成员的偏移的做法是:将0地址强制转换为TYPE * 类型的指针,所以0指针指向的TYPE类型的成员的地址都是以相对于0地址的偏移,所以返回成员的地址,就是要获得的偏移。
3. container_of的定义
/** * container_of - 通过三个参数,返回指向数据结构的指针 * @ptr: 数据结构中指向某一成员的指针 * @type: 数据结构类型 * @member: 在数据结构中的成员 * */
#define container_of(ptr, type, member) ({
\ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
- 首先,将0地址强制转换为type * 指针。
- 然后,再使用typeof()获取名为member成员的数据类型
- 接着,定义一个临时成员变量指针__ptr,让它指向已知的成员变量指针ptr。
- 然后,获取这个成员变量在这个数据结构的偏移量。
- 最后,现在已经知道成员member的地址以及在数据结构的偏移量,将__mptr强制转换为char * 再减去偏移量就是要获取数据结构的地址。
4. 例子
test.c源文件
#include <stdio.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) );})
typedef struct profile
{
char *name;
unsigned int age;
char *sex;
}profile_t;
static profile_t prop = {
.name = "wzc",
.age = 18,
.sex = "male"
};
int main()
{
profile_t *p = container_of(&prop.sex, struct profile, sex);
printf("name = %s, age = %u, sex = %s\n", p->name, p->age, p->sex);
printf("This number is = %d\n", ({
1;2;3;4;}));
return 0;
}
运行结果:
4.1 获取预编译文件test.i
$ gcc -E test.c -o test.i
# 8 "test.c"
typedef struct profile
{
char *name;
unsigned int age;
char *sex;
}profile_t;
static profile_t prop = {
.name = "wzc",
.age = 18,
.sex = "male"
};
int main()
{
profile_t *p = ({
const typeof( ((struct profile *)0)->sex ) *__mptr = (&prop.sex); (struct profile *)( (char *)__mptr - ((size_t) &((struct profile *)0)->sex) );});
printf("name = %s, age = %u, sex = %s\n", p->name, p->age, p->sex);
printf("This number is = %d\n", ({
1;2;3;4;}));
return 0;
}
4.2 container_of宏定义中的“({})”解释
刚开始,对container_of()为什么能够有返回值有疑惑,它明明没有return语句,并且还是块语句(因为在大括号{}中),然后将小括号去掉,只留大括号,发现可以预编译成功,但是编译生成可执行文件时报错。
最后想了一下,小括号中的东西看做一个整体,在大括号中的最后一个语句的值会作为返回值,实验了一下,确实如此。
今天的文章container_of怎么用_picking on分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/70917.html