亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

offsetof與container_of宏分析

標簽:
Linux

offsetof宏:结构体成员相对结构体的偏移位置
container_of:根据结构体成员的地址来获取结构体的地址

offsetof 宏

原型:

#define offsetof(TYPE, MEMBER)  ((size_t)&((TYPE *)0)->MEMBER)

(TYPE *)0非常巧妙,告诉编译器有一个指向结构体 TYPE 的指针,其地址是0,然后取该指针的 MEMBER 地址 &((TYPE *)0)->MEMBER,因为基址是0,所以这时获取到的 MEMBER 的地址就是相当于在结构体 TYPE 中的偏移量了。
Example:

#include <stdlib.h>#include <stdio.h>#include <stddef.h>struct TYPE{
    int mem;    int member;
};int main(){    struct TYPE type;
    printf("&type = %p\n", &type);    printf("&type.member = %p\n", &type.member);    printf("&((struct type *)0)->member = %lu\n", ((size_t)&((struct TYPE *)0)->member) );    printf("offsetof(struct TYPE member) = %zd\n", offsetof(struct TYPE, member));    return 0;
}/*
result:
&type = 0x7ffc1104a110
&type.member = 0x7ffc1104a114
&((struct type *)0)->member = 4
offsetof(struct TYPE member) = 4
*/

container_of 宏

原型:linux-4.18.5

/**
 * 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) ({              \
    void *__mptr = (void *)(ptr);                   \
    BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
             !__same_type(*(ptr), void),            \             "pointer type mismatch in container_of()");    \
    ((type *)(__mptr - offsetof(type, member))); })

网上所见更多是底下这个版本:

#define container_of(ptr, type, member) ({      \   
 const typeof( ((type *)0)->member ) *__mptr = (ptr);    \  
  (type *)( (char *)__mptr - offsetof(type,member) );})

第一部分:void *__mptr = (void *)(ptr);const typeof( ((type *)0)->member ) *__mptr = (ptr);
两个的差别在于 __mptr 的类型一个是 void * ,一个是 type *。
void * 较为容易理解,下面来看看 type *:
关于 typeof 关键字其作用是返回变量的类型,简单理解就是如下,详细可参见GCC typeof在kernel中的使用——C语言的“编译时多态”

int a;typeof(a) b; //这等同于int b;typeof(&a) c; //这等同于int* c;

因此const typeof( ((type *)0)->member ) *__mptr = (ptr);的作用就是通过 typeof 获取结构体成员 member 的类型,然后定义一个这个类型的指针变量 __mptr 并将其赋值为 ptr。
第二部分:(type *)( (char *)__mptr - offsetof(type,member) ),通过offsetof宏计算出 member 在 type 中的偏移,然后用 member 的实际地址__mptr减去偏移,得到 type 的起始地址。从上面关于offsetof宏的 Example 也可以验证这一点:
&type.member = 0x7ffc1104a114 - &((struct type *)0)->member = 4 = &type = 0x7ffc1104a110

原文出处:https://www.cnblogs.com/ZhaoxiCheung/p/9610721.html

點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消