在C语言中,有时候我们需要从成员变量的指针来获得对象所在的地址,这时候可以使用container_of宏实现。这个宏定义在Linux内核中,并且已经被广泛地应用于其他开源项目中。
container_of宏定义如下:
#define container_of(ptr, type, member) ({
const typeof(((type *)0)->member) *__mptr = (ptr);
(type *)((char *)__mptr - offsetof(type, member)); })
其中,ptr表示成员变量的指针,type表示包含该成员变量的结构体类型,而member则是该成员变量的名称。
container_of宏的实现原理是利用offsetof宏计算出成员变量在结构体中的偏移量,然后通过指针运算得到结构体的首地址。
下面是一个简单的示例程序,演示了如何使用container_of宏:
c
#include <stdio.h>
#include <stddef.h> // for offsetof macro
struct person {
char name[20];
int age;
};
struct node {
struct person data;
struct node *next;
};
int main() {
struct person *p;
struct node n = {{"John", 25}, NULL};
struct node *pn = &n;
p = &pn->data; // get the address of the person struct
struct node *container = container_of(p, struct node, data);
printf("Person's name: %s ", container->data.name);
printf("Person's age: %d ", container->data.age);
return 0;
}
在这个示例程序中,我们定义了两个结构体:person和node。其中,person结构体表示一个人的基本信息,而node结构体包含一个person结构体和下一个节点的指针。
在main函数中,我们首先获取了person结构体的地址,然后通过container_of宏获得了node结构体的地址。最后,我们就可以方便地访问node结构体中的成员变量了。
总之,container_of宏是一种非常方便的方法,可以让我们从成员变量的指针中获得包含该成员变量的结构体的地址。这个宏已经被广泛地应用于各种开源项目中,并且是一种C语言编程中非常重要的技巧。