offsetof与container_of宏的理解-创新互联

这两个是在linux内核中经常用到的两个宏,先说offsetof这个宏的作用就是来计算在结构体中的一个元素与结构体地址的偏移量。结构体的元素访问其实就是指针访问,直接应用的时候是用一个点来访问的但是其实在底层经过编译器编译后的执行程序还是用这个偏移量的地址来访问的例如定义一个结构体如下
typedef struct test{
char t1;
int t2;
short t3;
}test;
int main(void)
{
test s1;
s1.t1='a';
s1.t2=123;
s1.t3=456;

坚守“ 做人真诚 · 做事靠谱 · 口碑至上 · 高效敬业 ”的价值观,专业网站建设服务10余年为成都社区文化墙小微创业公司专业提供企业网站建设营销网站建设商城网站建设手机网站建设小程序网站建设网站改版,从内容策划、视觉设计、底层架构、网页布局、功能开发迭代于一体的高端网站建设服务。

return 0;

}
这种用点的形式直接访问其本质是如下的:

test p;
char
p1;
int p2;
short
p3;
p=&s1;
p1=(char )((int)p+0)
p2=(int
)((int)p + 4);
p3=(short *)((int)p + 8);

printf("*p1 = %c.\n",*p1);
printf("*p2 = %d.\n",*p2);
printf("*p3 = %d.\n",*p3);
这样得到结构是完全正确的意思就是这个偏移量很重要,所有就产生了offsetof这个宏,他的原型是
#define offsetof(Type,Member)  ((int)&((Type*)0)->Member)
首先有两个参数Type是指这个结构体的类型名,member就是这个结构体的成员名经过这个宏之后就返回了一个×××数是这个成员变量在这个结构体中相对于结构体地址的偏移量这里边有一个(Type*)0)最不好理解意思就是假设了一个type类型的结构体他的地址是在地址0处其实这个结构体是不存在的但是这样假定使用是不会有问题的,因你又没有引用这个地址所有就没有问题了,其实返回的这个数就是这个成员的地址减去结构体的地址但是因为结构体的地址是0所有就能直接返回这个成员的地址而也正因为结构体的地址是零所有成员的地址也就正好是偏移量了。
而container_of这个宏就是在offsetof这个宏的基础上发展来的他的作用就是知道一个结构体中的成员的地址通过这个宏的运算后得到了结构体的地址,这个就厉害了因为你只要知道了结构体的指针那么你就可以得到结构体中的任何一个元素。这个宏的源型是#define container_of(ptr,type,member)  ({\

Const typeof(((type)0)->member) mptr = (ptr);\
(type)((char)
mptr - offsetof(type,member));})

有三个参数ptr是结构体中元素的指针,type是结构体的类型名,member是这个ptr指针的结构体元素名。这个宏里第一条我觉得其实也没什么用去掉应该也可以因为他只是得到了这个结构体中成员变量的类型,之后这个成员变量的地址减去他在结构体中的偏移量那得到的就是结构体的指针在将类型强制转换为结构体指针就可以了。

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


文章题目:offsetof与container_of宏的理解-创新互联
转载来源:http://azwzsj.com/article/dgjedh.html