结构体中元素的偏移地址与首地址

结构体中元素的偏移地址与首地址

1、offsetof()

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

它是#include <stddef.h>中的一个宏
目的是:获取一个结构体成员在结构里面的偏移,结构体首地址 = 成员地址- 成员偏移

这里是引用

0指针的使用

#include<stdio.h>
 
struct test
{
 	char i ;
 	int j;
 	char k;
};
 
int main()
{
 	struct test temp;
 	printf("&temp = %p\n",&temp);   
 	printf("&temp.k = %p\n",&temp.k);
 	printf("&((struct test *)0)->k = %d\n",((int)&((struct test *)0)->k));
 	printf("sizeof(temp) = %d\n", sizeof(temp));
 
 	return 0
}
	&temp = 0061FF14
	&temp.k = 0061FF1C
	&((struct test *)0)->k = 8
	sizeof(temp) = 12

1、通过自定义结构体的三个变量:i, j, k可得,因为有字节对齐的要求,所以该结构的大小为4 bytes * 3 = 12 bytes,而 &(( struct test *) 0)->k的作用就是求k到结构体temp起始地址的字节数大小(size)。
2、在这里0被强制转化为struct test *型, 它的作用就是作为指向该结构体起始地址的指针, 而&((struct test *)0)->k 的作用便是求k到该起始指针的字节数。。。其实是求相对地址,起始地址为0,则&k的值便是size大小(注:打印时因为需要整型,所以有个int强转)所以我们便可以求我们需要的 size 了 。

2、container_of()

在这里插入图片描述

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

第二行:const typeof( ((type *)0)->member ) *__mptr = (ptr);
目的:当开发者使用时输入的参数有问题:ptr与member类型不匹配,编译时便会有warnning, (防止出错有不知道错误在哪里),它的作用是获取member的类型仅此而已。

container_of ( ptr, type, member ) 函数的实现包括两部分:

  • 判断ptr 与 member 是否为同一类型
  • 计算size大小,结构体的起始地址 = (type *)((char *)ptr - size) (注:强转为该结构体指针)
    现在我们知道container_of( )的作用就是通过一个结构变量中一个成员的地址找到这个结构体变量的首地址。
  • container_of(ptr, type, member),这里面有ptr, type, member分别代表指针、类型、成员。
#include <stdio.h>  
#include <stdlib.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 ptr  
{  
    char a ;   
    short b ;   
    int  c ;   
    double d ;  
};  
 
int main(void)  
{  
    struct ptr Pt ;  
    struct ptr *pt ;
    printf("ptr:%d\n",sizeof(struct ptr));//16  
    //获取结构体的首地址 
    printf("ptr:%p\n",&Pt);   //0061FF08
    Pt.a = 'a';
    Pt.b = 2 ;
    Pt.c = 4 ;
    Pt.d = 12.04 ;
    //通过container of获取结构体的首地址 
    pt = container_of(&Pt.c, struct ptr , c);
    printf("pt:%p\n",pt);     //0061FF08
    printf("a:%c\n",pt->a) ;  //'a'
    printf("b:%d\n",pt->b) ;  //2
    printf("c:%d\n",pt->c) ;  //4
    printf("d:%.2lf\n",pt->d);//12.04
    
    return 0 ;  
}  
ptr:16
ptr:0061FF08
pt:0061FF08
a:a
b:2
c:4
d:12.04
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值