c语言通过结构体元素找到结构体指针
背景
有以下需求
1.假设我们只知道 A 的地址,struct1 的地址是不知道的
2.那么如何通过 A 的地址去找到 struct1 的地址呢?
#include <stdio.h>
typedef struct MyStruct1
{
int a ;
char b ;
int c ;
} Struct;
Struct struct1 = { 1,'B',4 };
// 主函数
int main(int argc, char **argv)
{
// 假设我们只知道 A 的地址,struct1 的地址是不知道的
// 那么如何通过 A 的地址去找到 struct1 的地址呢?
int A = struct1.c;
return 0;
}
解决方案1
#include <stdio.h>
typedef struct MyStruct1
{
int a ;
char b ;
int c ;
char d[10];
} Struct;
Struct struct1 = { 99,'B',100, "HHH" };
// 主函数
int main(int argc, char **argv)
{
// 假设我们只知道 A 的地址,连 struct1 的地址都不知道
// 那么如何通过 A 去访问到 a b c呢?
char *A = &struct1.b;
// 找到 A 与结构体首地址的偏差
int offset = (int)&((Struct*)0)->b - (int)&((Struct*)0)->a;
// 地址偏移到结构体首地址
Struct* dst = (Struct*)((char*)A - offset);
// 完成
printf("a=%d\n", dst->a);
printf("b=%c\n", dst->b);
printf("c=%d\n", dst->c);
printf("d=%s\n", dst->d);
printf("struct1 的地址:%p\n", &struct1);
printf(" dst 的地址:%p\n", dst);
return 0;
}
调试结果:
以上的方式是通过地址偏移的方式可得到想要的地址,但感觉不是很好用。
后借鉴 linux 内核源码的两个宏定义
* desc : a simple example to use container_of() macro
* mail : xzpeter@gmail.com
*/
#include <stdio.h>
#ifndef offsetof
#define offsetof(type, field) ((long) &((type *)0)->field)
#endif /* offsetof */
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
根据以上宏定义,我们对解决方案代码做相应的修改
#include <stdio.h>
typedef struct MyStruct1
{
int a ;
char b ;
int c ;
char d[10];
} Struct;
Struct struct1 = { 99,'B',100, "HHH" };
#define offsetof(type, field) ((long) &((type *)0)->field)
#define container_of(ptr, type, member) (type *)((char *)ptr - offsetof(type, member))
// 主函数
int main(int argc, char **argv)
{
// 假设我们只知道 A 的地址,连 struct1 的地址都不知道
// 那么如何通过 A 去访问到 a b c呢?
char *A = &struct1.b;
// 通过结构体元素获取到结构体首地址
Struct* dst = container_of(A, Struct, b);
// 完成
printf("a=%d\n", dst->a);
printf("b=%c\n", dst->b);
printf("c=%d\n", dst->c);
printf("d=%s\n", dst->d);
printf("struct1 的地址:%p\n", &struct1);
printf(" dst 的地址:%p\n", dst);
return 0;
}
调试结果:
这样我们就只需要向 container_of 填写相应的参数就能获取结构体地址啦。
_End
完事儿。
本文来自博客园,作者:想想就很离谱,转载请注明原文链接:https://www.cnblogs.com/lvvou/p/15689995.html