offsetof 宏

在 <stddef.h> 中定义了个 offsetof(s,m)宏,这个宏用来取得结构体中元素的偏移量很方便,下面是此宏的具体定义:

#define offsetof(s, m) (size_t)&(((s *)0)->m)

ofssetof(s, m) 其中,s 是结构体名,m 是它的一个成员。s 和 m 同是宏  offsetof() 的形参,这个宏返回的是结构体 s 的成员 m 在结构体中的偏移地址。

(s *)0  :  这里的用法实际上是欺骗了编译器,使编译器认为 "0" 就是一个指向 s 结构体的指针(地址),还句话说 s 结构体就是位于 0x0 这个地址处。

(s *)0-> m : 自然就是指向这个结构体的 m 元素。

&((s *)0)->m :  表示 m 元素的地址。这里,如上面所说,因为编译器认为结构体 s 被认为是处于 0x0 地址处,所以 m 的地址自然的就是 m 在 s 中的偏移地址了。

最后将这个偏移值转化为 size_t 类型。

可能会感到迷惑,这样强制转换后的结构指针怎么可以用来访问结构体字段?呵呵,其实这个表达式根本没有也不打算访问m字段。ANSIC标准允许任何值为0的常量被强制转换成任何一种类型的指针,并且转换结果是一个NULL指针,因此((s*)0)的结果就是一个类型为s*的NULL指针。如果利用这个NULL指针来访问s的成员当然是非法的,但&(((s*)0)->m)的意图并非想存取s字段内容,而仅仅是计算当结构体实例的首址为((s*)0)时m字段的地址。聪明的编译器根本就不生成访问m的代码,而仅仅是根据s的内存布局和结构体实例首址在编译期计算这个(常量)地址,这样就完全避免了通过NULL指针访问内存的问题。又因为首址的值为0,所以这个地址的值就是字段相对于结构体基址的偏移。

size_t是针对系统定制的一种数据类型。它不是固定位数,在不同的系统里这个值都有可能不同( 它实际上是 unsigned int 类型 );而且在内存里,对于数据是高位对齐存储还是低位对齐存储各系统都不一样。所以,为了提高代码的可移植性,就有必要定议这样的数据类型。一般这种类型都会定义到它具体占几位内存等。当然,有些是编译器或系统已经给定义好的。具体要查看技手册。

10月29日

欺骗编译器的#define offsetof(s,m) (size_t)&(((s *)0)->m)

在MPC8323上使用到SEC,在文件sec2.h的L58中,涉及这样的语句:
#ifndef offsetof
#define offsetof(s,m)   (size_t)&(((s *)0)->m)
#endif
琢磨半天也比较头疼那个0的含义,感觉就是转化一个0为s结构,获取成员m的地址。但是,为啥是0呢?为啥呢?
搜索了才发现,原来这个东西也很巧妙。
(s   *)0   是骗编译器说有一个指向类(或结构)s的指针,其值0。
&(((s   *)0)->m)   是要取得类s中成员变量m的地址,由于这个类的基址为0,这时m的地址当然就是m在s中的偏移了。
代码巧妙的地方就在于用0来表示这个指针,0成为了这个类/结构的基址,所以成员的地址就成了偏移地址。
或许这也是代码精巧所在吧!

offsetof 详解相关推荐

  1. 面试常考,项目易错,长文详解C/C++中的字节对齐

    作者 | 李肖遥 来源 | 技术让梦想更伟大(ID:TechDreamer) 头图 |  CSDN 下载自东方IC 引入主题,看代码 我们先来看看以下程序 //编译器:https://tool.lu/ ...

  2. Android init.rc文件解析过程详解(三)

    Android init.rc文件解析过程详解(三) 三.相关结构体 1.listnode listnode结构体用于建立双向链表,这种结构广泛用于kernel代码中, android源代码中定义了l ...

  3. 位地址和字节地址换算_面试常考,项目易错,长文详解C/C++中的字节对齐

    (给CPP开发者加星标,提升C/C++技能) 作者:技术让梦想更伟大 / 李肖遥 (本文来自作者投稿) 我们先来看看以下程序 //编译器:https://tool.lu/coderunner///来源 ...

  4. 转 C++宏定义详解

    来自:传送门 C++宏定义详解 一.#define的基本用法 #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往 ...

  5. C语言中sizeof详解——面试C/C++

    C面试sizeof详解 1.定义 sizeof是C语言的一种单目操作符,它并不是函数.sizeof操作符以字节形式给出了其操作数所占存储空间的大小.操作数可以是一个表达式或括在括号内的类型名.操作数所 ...

  6. C 和 C++ 宏 详解

    From:https://www.cnblogs.com/njczy2010/p/5773061.html C中的预编译宏详解:http://www.cppblog.com/bellgrade/arc ...

  7. sizeof,strlen用法详解

    sizeof 前向声明: sizeof,一个其貌不扬的家伙,引无数菜鸟竟折腰,小虾我当初也没少犯迷糊,秉着"辛苦我一个,幸福千万人"的伟大思想,我决定将其尽可能详细的总结一下. 但 ...

  8. container_of详解

    container_of详解 #define container_of(ptr, type, member) ({                      \ const typeof(((type ...

  9. 64位 int 占几个字节_面试常考,项目易错,长文详解C/C++中的字节对齐

    面试常考,项目易错,长文详解C/C++中的字节对齐​mp.weixin.qq.com 引入主题,看代码 我们先来看看以下程序 //编译器:https://tool.lu/coderunner/ //来 ...

最新文章

  1. HBM2E Flashbolt--提升人工智能的算力
  2. mongodb学习笔记6--杂项与补充
  3. 这个搞定系统监控的妙招,不来学可惜了
  4. Hibernate执行原理总结
  5. 马哥2016全新Linux+Python高端运维班第七周作业
  6. zsh 主题的下载和安装
  7. flash 火狐总是崩溃_win10系统火狐flash插件总是崩溃的解决方法
  8. CentOS7 下安装 Redis
  9. echarts中graphic_Echarts实现折线图
  10. php滑动门效果,JavaScript实现滑动门效果
  11. Java贪吃蛇(附完整代码下载链接)-跟随狂神一天完成
  12. Intelij的IDEA启动报错!parent directory is read-only or the user lacks necessary permissions
  13. ArcGIS地图制图教程——超详细
  14. “物联网×”:“互联网+”的下一个风口
  15. 【论文阅读】UAV-Based Crop and Weed Classification for Smart Farming
  16. 王者荣耀静态页面头部代码设计(2)
  17. dd命令 刻录U盘启动
  18. LNK1181:无法打开输入文件“release/.obj“
  19. 最小生成树 | Prim算法 Kruskal算法 |C语言
  20. 版本管理工具 git和SVN 忽略文件和目录

热门文章

  1. 专升本英语——语法知识——高频语法——第二节 谓语动词【学习笔记】
  2. Django搭建个人博客Blog-Day05
  3. excel求方差和标准差的函数_Excel标准差计算函数Stdev和StdevP的用法与区别,包含4个实例...
  4. windows10/11通过蓝牙传输文件
  5. DirectX(dll)修复软件推荐4.2增强版
  6. 各种安装包的下载地址
  7. 特殊符号: 和 | | 和 ?? 和 ?作用详解
  8. 痛惜!年仅43岁,又一位985高校博导因病逝世
  9. Crack:::Stimulsoft Ultimate 2023.1.2
  10. mapBox使用笔记