最近参加XX面试,被问到“如何根据一个结构体变量的成员,找到该结构体变量的地址”。想到Linux内核代码中有个container_of可以处理。
container_of是一个宏,其定义如下:
-
/**
-
* container_of - cast a member of a structure out to the containing structure
-
* @ptr: the pointer to the member.
-
* @type: the type of the container struct this is embedded in.
-
* @member: the name of the member within the struct.
-
*
-
*/
-
-
#define container_of(ptr, type, member) ({ \
-
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
-
(type *)( (char *)__mptr - offsetof(type,member) );})
根据上面定义,要实现container_of,首先需要实现一个获取结构体变量成员地址与该结构体变量地址的距离:offsetof.
下面来动手实现:
-
#define OFFSET(type, mem)(size_t)(&(((type*)0)->mem))
上面宏中的 type基地址为0,那么mem的地址就是mem成员相对于type头地址的偏移量。
仿照container_of:
-
#define CONTAINER_OF(pointer, type, member) (type*)(((char*)pointer - OFFSET(type, member)))
pointer是已知的结构体type的某个成员的地址,type是结构体类型,member是pointer对应的成员名。
(注:需使用char*强转pointer类型,得到正确的偏移)
下面以一个实例程序帮助理解:
-
#include <stdlib.h>
-
#include <stdio.h>
-
#include <string.h>
-
-
#define OFFSET(type, mem)(size_t)(&(((type*)0)->mem))
-
#define CONTAINER_OF(pointer, type, member) (type*)(((char*)pointer - OFFSET(type, member)))
-
-
typedef struct A
-
{
-
int data;
-
int mem;
-
char str[10];
-
}A_t;
-
-
int main(void)
-
{
-
A_t a = {
-
.data = 100,
-
.mem = 20,
-
};
-
A_t *b = NULL;
-
strncpy(a.str, "Tencent", sizeof(char)*8);
-
-
printf("offset of a.data: %u\n", OFFSET(A_t, data));
-
printf("offset of a.mem: %u\n", OFFSET(A_t, mem));
-
printf("offset of a.str: %u\n", OFFSET(A_t, str));
-
-
b = CONTAINER_OF((&a.mem),A_t,mem);
-
printf("address of a is : %p\n", &a);
-
printf("address of b is : %p\n", b);
-
printf("data is : %d\n", b->data);
-
printf("mem is : %d\n", b->mem);
-
printf("str is : %s\n", b->str);
-
-
b = CONTAINER_OF((&a.str), A_t, str);
-
printf("data is : %d\n", b->data);
-
printf("mem is : %d\n", b->mem);
-
printf("str is : %s\n", b->str);
-
-
return 0;
-
}
程序运行结果如下:
-
offset of a.data: 0
-
offset of a.mem: 4
-
offset of a.str: 8
-
address of a is : 0x7fff5fae64c0
-
address of b is : 0x7fff5fae64c0
-
data is : 100
-
mem is : 20
-
str is : Tencent
-
data is : 100
-
mem is : 20
-
str is : Tencent
阅读(1089) | 评论(0) | 转发(0) |