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

  • 1、offsetof()
    • 0指针的使用
  • 2、container_of()

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 = 8sizeof(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);   //0061FF08Pt.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);     //0061FF08printf("a:%c\n",pt->a) ;  //'a'printf("b:%d\n",pt->b) ;  //2printf("c:%d\n",pt->c) ;  //4printf("d:%.2lf\n",pt->d);//12.04return 0 ;
}
ptr:16
ptr:0061FF08
pt:0061FF08
a:a
b:2
c:4
d:12.04

结构体中元素的偏移地址与首地址相关推荐

  1. 驱动下通过进程PID获得进程名 (动态获取ImageFileName在EPROCESS结构体中的相对偏移)...

    思路 进程EPROCESS结构体中含有进程名ImageFileName(需求处ImageFileName在EPROCESS结构体中的相对偏移)-->获得进程EPROCESS-->通过进程句 ...

  2. 结构体中元素引用—— “.“ 与 “->“

    自从了解结构体这个类型后,相信有不少人和我一样对于 "." 和 "->"何时使用哪个来引用目标结构体中元素感到混淆,今天还是把他写下来,以后再忘了自己也可 ...

  3. 【DaVinci Developer专题】-24-IDT高阶应用:结构体中元素(数组,结构体,联合体)类型相互嵌套

    共15页 目录 1 创建一个Value IDT 2 创建一个Array IDT 3 创建一个Record IDT 4 创建一个Union IDT 5 创建一个Record IDT <

  4. C语言 泛型链表 如何计算(结构体中各元素)相对内存地址?(字节对齐,结构体对齐)offsetof()函数 ( (struct X*)0 ) -> Y)语法(匿名结构体)

    示例: typedef struct _user {char name[20];char sex[20];int age;struct list_head mylist;//自定义结构体里保存双向循环 ...

  5. 【C语言】宏offsetof的模拟实现 (计算结构体中某变量相对于首地址的偏移)

    首先我们应该特别留意 : offsetof 是一个宏,并非是一个函数 ! 宏offsetof的介绍 : 参数:第一个是结构体类型名称,第二个是结构体成员名 返回类型:size_t无符号整形 引用的头文 ...

  6. C语言中利用宏,实现一个整数的奇数位和偶数位交换,以及计算结构体中某变量相对于首地址的偏移

    C语言中的自定义宏 自定义宏,令其实现所需功能 1.写一个宏,可以将一个整数字的奇数位和偶数位交换. 2.写一个宏,计算结构体中某变量相对于首地址的偏移. 具体思路1: 首先取出当前数的奇数部分和偶数 ...

  7. C语言如何获取结构体中指定元素的大小?sizeof ( (X*)0 ) -> Y)(空指针操作)

    获取结构体的大小,这好办,这样就可以了: #include <stdio.h>struct user {char name[20];char age[10]; };int main() { ...

  8. 结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法

    结构体中最后一个成员为[0]长度数组的用法:这是个广泛使用的常见技巧,常用来构成缓冲区.比起指针,用空数组有这样的优势:(1).不需要初始化,数组名直接就是所在的偏移:(2).不占任何空间,指针需要占 ...

  9. C/C++ 学习笔记:结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法

    结构体中最后一个成员为[0]长度数组的用法:这是个广泛使用的常见技巧,常用来构成缓冲区.比起指针,用空数组有这样的优势:(1).不需要初始化,数组名直接就是所在的偏移:(2).不占任何空间,指针需要占 ...

最新文章

  1. pandas中的3种基本数据类型介绍
  2. linux命令行终端的翻屏滚屏,linux命令行终端的翻屏滚屏more/less/head/tail
  3. 李志飞:想在中国复制 Echo 的成功,肯定都不靠谱
  4. Mysql常用命令详解
  5. 9个元素换6次达到排序序列_(算法四)高级排序(快速排序)
  6. boost::multiprecision模块实现导入/导出 cpp_int 的位 到 8 位无符号值的向量相关的测试程序
  7. rzsz for linux,linux下如何安装rzsz
  8. 自动化运维平台中的统一认证接入与单点登录实现
  9. 转:谷歌离线地图基础
  10. 使用Apache CXF开发RESTful服务
  11. Linux shell 脚本SDK 打包实践, 收集assets和apk, 上传FTP
  12. Hyper-v 开启嵌套虚拟化的方法
  13. Elasticsearch核心知识大纲脑图
  14. 在线教学战“疫”打响,VIPKID背后是阿里云
  15. kali wifi 无线渗透测试 网卡桥接搭建无赖AP
  16. PHP 7从零基础到项目实战,PHP 7从零基础到项目实战
  17. AI洞观 | 一文读懂2018安博会四大趋势
  18. 重庆涪陵创新计算机职业学校文艺表演,涪陵信息技术学校2017年元旦文艺汇演...
  19. 家居收纳打造一个美好的家-央央家政家居收纳
  20. 夏普清除小太阳和小人的方法

热门文章

  1. Hall of Fame
  2. 我今天心情不好,说一些安慰我的话
  3. 十六倍数看视视频,无需会员,两行代码解决
  4. python 无法导入cpython的.pyx文件
  5. 【成功励志故事】永远不能放弃!
  6. 蓝桥杯 2014 C++B(5) Log大侠 线段树 区间修改
  7. android指纹识别真机,vivo屏下指纹真机试玩:支持湿手解锁,最快月底发布
  8. 算法与数据结构 - 字节跳动笔试题
  9. java如何将字符串写入到txt文件中,值得收藏!
  10. jquery 获取父页面Id 值