写一个宏container_of(ptrtypemember),通过type类型的结构体中成员变量member的地址ptr,求取该结构体的首地址
时间: 2024-02-25 17:55:40 浏览: 83
可以使用以下宏定义实现container_of(ptr, type, member)的功能:
```c
#define container_of(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type, member)))
```
其中,`ptr`表示成员变量`member`的地址,`type`表示所在的结构体类型,`member`表示结构体中的成员变量名。
宏定义中使用了C语言标准库中的`offsetof`宏,该宏用于计算结构体中成员变量的偏移量,其定义如下:
```c
#define offsetof(type, member) ((size_t) & ((type *)0)->member)
```
这里使用了一个特殊的技巧,将一个空指针`(type *)0`转换为指向结构体类型`type`的指针,再通过`&`运算符获取成员变量`member`在结构体中的偏移量,最终计算出结构体的首地址。
因此,`container_of`宏的实现原理就是,通过成员变量`member`的地址,在结构体中的偏移量计算出结构体的首地址,然后将其强制转换为`type`类型的指针返回。
相关问题
linux内核宏container_of如何使用?
在 Linux 内核中,`container_of` 是一个非常常用的宏,它可以通过结构体中某个成员的地址来获取整个结构体变量的地址。
使用方法如下:
```c
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
/* 示例结构体 */
struct student {
char name[20];
int age;
int score;
struct list_head list;
};
/* 示例使用 */
struct student stu;
struct list_head *pos;
/* 假设我们已经有一个指向 list_head 的指针 pos,需要获取整个 student 结构体的地址 */
pos = &stu.list;
struct student *pstu = container_of(pos, struct student, list);
```
这里的 `ptr` 是指向结构体中某个成员的指针,`type` 是结构体的类型,`member` 是结构体中的成员名。
`offsetof` 是另一个宏,用于获取结构体中某个成员相对于结构体起始地址的偏移量。
值得注意的是,`container_of` 宏使用了 GNU 扩展的语法,因此在编译时需要添加 `-std=gnu99` 选项。
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})中typeof
在这段代码中,typeof 是一个编译器内置的操作符,用于返回表达式的数据类型。在该宏定义中,typeof( ((type *)0)->member ) 用于获取结构体成员变量 member 的数据类型。该表达式是通过将一个指向类型为 type 的空指针强制转换为指向类型为 type 成员变量 member 的指针,然后取该指针所指向的成员变量的数据类型。由于该指针指向的是空指针,因此不会发生内存访问错误。然后,通过 const 修饰符将这个类型指针声明为指向常量的指针,以避免对其进行修改。最终,宏定义会返回一个指向类型为 type 的结构体变量的指针,这个指针指向的结构体变量的成员变量 member 的地址与输入的指针变量 ptr 相对偏移的位置。
阅读全文