说明:
本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
内容来源:
目录:
1.功能简介:
2.源码及注释:
/**
* @brief 通过“结构体成员”的地址与“结构体”的类型推导出“结构体”的首地址
*
* @ptr: “结构体成员”的地址
* @type: “结构体”的类型
* @member: “结构体成员”的名字
*/
#ifndef container_of
#define container_of(ptr, type, member) \
({ \
const typeof(((type *)NULL)->member) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); \
})
#endif
/*
(1).typeof()返回传入数据的类型,如int a = 3;typeof(a) = int
(2.offsetof(type, member):在类型为type的结构体中member成员,在该结构体中的偏移量
type:结构体类型,member:结构体中某个成员
分析:
A = ((type *) NULL)表示:type类型的指针地址为0,
B = (A->member)表示:该结构体类型(地址为0)的成员member
C = typeof(B)表示:返回结构体成员member的数据类型
D = const C* __mptr = (ptr)表示:__mptr的地址为ptr的成员地址(数据类型统一的成员地址)
E = offsetof(type, member)表示:类型为type的结构体中member成员,member在该结构体中的偏移量
F = (type *) ((char *)__mptr - E
= ptr - E (忽略类型) = 成员的地址 - 成员的偏移量 = 结构体的的初始地址 = 结构体指针地址
*/
3.源文件测试理解步骤
#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#ifndef container_of
#define container_of(ptr, type, member) \
({ \
const typeof(((type *)NULL)->member) *__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); \
})
#endif
struct test_struct
{
int data;
bool pending;
char name;
void *pointer;
};
int main(int argc, char *argv[])
{
/*
1.理解typedef关键字的作用
typeof(((struct test_struct *)NULL)->name) = char
typeof()返回传入数据的类型,如int a = 3;typeof(a) = int
*/
const typeof(((struct test_struct *)NULL)->name) a = 'a';
printf("%c\n", a);
/*
2.获取结构体成员的地址
const typeof(((type *)NULL)->member) *__mptr = (ptr);
根据结构体成员名得到结构体成员名的数据类型,再将已知的成员地址传入
*/
struct test_struct data;
const typeof(((struct test_struct *)NULL)->name)* _a = &data.name;
printf("member address:%p\n", _a);
/*
3.获取结构体成员的地址与结构体的偏移量
offsetof(type, member)
在类型为type的结构体中member成员,在该结构体中的偏移量
*/
printf("member offset:%ld\n", offsetof(struct test_struct, name));
/*
4.最终结果,获得结构体地址
*/
printf("struct address:%p\n", \
(struct test_struct *)((char *)_a - offsetof(struct test_struct, name)));
printf("struct address:%p\n", &data);
return 0;
}
评论(0)
您还未登录,请登录后发表或查看评论