求结构体成员变量的偏移值和结构体的首地址宏

offset宏:求结构体成员变量的偏移值。

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

(1) offset宏的作用是:用宏来计算结构体某个元素和接哦固体首地址的偏移量(实质是通过编译器来帮助我们计算)

(2) offset宏的原理:我们虚拟一个type类型结构体变量,然后用type.member的方式来访问那个member元素,整个结构体变量的首地址是0,相当于整个结构体变量的起始地址是0,而member元素的首地址是&((TYPE*)0)->MEMBER,所以这个数字减去0还是这个数字,取到的结构体成员的绝对地址就变成了member元素相当于整个结构体变量首地址的偏移量

对于这个宏可以大致分为5步:

对这个宏的讲解我们大致可以分为以下4步进行讲解:

0)   0  //内存地址开始于0

1)  ( (TYPE *)0 )   //0地址强制 "转换" 为 TYPE结构类型的指针;

2)   ((TYPE *)0)->MEMBER   //引用TYPE结构中的MEMBER数据成员

3)  &( ( (TYPE *)0 )->MEMBER)  //取地址符&, 取出TYPE结构中的数据成员MEMBER的地址

4)   (size_t)(&(((TYPE*)0)->MEMBER))   //将取到的地址强制转化为size_t类型。

 

代码只所以没有风险,是因为这里面没有写任何内存地址,甚至没有访问任何内存位置。只是操作了指向这些位置的指针,而指针一般存储在机器寄存器或是本地堆栈中
 

container_of宏:根据成员地址、结构体类型和成员名来计算结构体的首地址

定义如下:

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

    创建一个结构体,用offsetof和container_of获取结构体的地址和内部成员相对于结构体地址的偏移量。

 

代码实例:

#include <stdio.h>

#define offsetof(type, member)       ((size_t)&((type *)0)->member)

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

上面宏的含义是先求出结构体成员的偏移地址,再用成员的实际地址减去偏移地址就得到了结构体的首地址

 

struct test{

    char a;

    int b;

    short c;

    char *p;

    double d;

}__attribute__((aligned(4)));

 

int main(int argc, char **argv)

{

    struct test s;

    printf("offset a=%lu\n",offsetof(struct test,a));

    printf("offset b=%lu\n",offsetof(struct test,b));

    printf("offset c=%lu\n",offsetof(struct test,c));

    printf("offset p=%lu\n",offsetof(struct test,p));

    printf("offset d=%lu\n",offsetof(struct test,d));

 

    printf("s=%p\n",container_of(&s.a,struct test,a));

    printf("s=%p\n",container_of(&s.p,struct test,p));

    return 0;

}

运行结果:

offset a=0

offset b=4

offset c=8

offset p=16

offset d=24

s=0x7fffc8590cf0

s=0x7fffc8590cf0

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值