container_of怎么用_picking on

container_of怎么用_picking oncontainer_of的用法1.container_of的用途说明2.offsetof的定义3.container_of的定义4.例子4.1获取预编译文件test.i4.2container_o

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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注