__builtin_offsetof()[通俗易懂]

__builtin_offsetof()[通俗易懂]————-linuxcompiler-gcc4.h————–#define__compiler_offsetof(a,b)__builtin_offsetof(a,b)分析准备:__compiler_offsetof(),为gcc编译器中的编译方面的参数,查阅gcc方面的文档:—>gcc.pdf.Downloadfromwww.gn

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

本文转载自  :  https://blog.csdn.net/rockhui/article/details/6304705 

————-linuxcompiler-gcc4.h————–
#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
分析准备:__compiler_offsetof(),为gcc编译器中的编译方面的参数,查阅gcc方面的文档:
—>gcc.pdf.Download from www.gnu.org 。其中解释如下:
#define offsetof(type, member) __builtin_offsetof (type, member)

自己分析:即:__builtin_offsetof(a,b)就是#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)。__builtin_offsetof(a,b)和offsetof(TYPE,MEMBER)本质一样的,只是 offsetof()宏是由程序员自己来设计(详见后面讲解)。而__builtin_offsetof()宏就是在编译器中已经设计好了的函数,直接调用即可。明白了这个区别后,下面的代码很好理解。

——-linuxstddef.h—–offsetof()———–
#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
——————————-
#undef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
1.对__compiler_offsetof()宏的分析:
__compiler_offsetof来确认编译器中是否内建了功能同offsetof()宏一样的宏。若已经内建了这样的宏,则 offsetof()就是使用这个内建宏__compiler_offsetof()即:__builtin_offsetof()宏。如果没有定义 __compiler_offsetof()宏,则offsetof()宏就由程序员来设计之。

2.对offsetof()宏的分析:(以下引用论坛)—曾经的腾讯QQ的笔试题。
宿舍舍友参加qq笔试,回来讨论一道选择题,求结构中成员偏移。
想起Linux内核链表,数据节点携带链表节点,通过链表访问数据的方法,用到offsetof宏,今天把它翻了出来:
#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER )

一共4步
1. ( (TYPE *)0 ) 将零转型为TYPE类型指针;
2. ((TYPE *)0)->MEMBER 访问结构中的数据成员;
3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址;
4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型.巧妙之处在于将0转换成(TYPE*),结构以内存空间首地址0作为起始地址,则成员地址自然为偏移地址;
举例说明:
#include<stdio.h>
typedef struct _test
{

char i;
int j;
char k;
}Test;
int main()
{

Test *p = 0;
printf(“%p “, &(p->k));
}
自己分析:这里使用的是一个利用编译器技术的小技巧,即先求得结构成员变量在结构体中的相对于结构体的首地址的偏移地址,然后根据结构体的首地址为0,从而得出该偏移地址就是该结构体变量在该结构体中的偏移,即:该结构体成员变量距离结构体首的距离。在offsetof()中,这个member成员的地址实际上就是type数据结构中member成员相对于结构变量的偏移量。对于给定一个结构,offsetof(type,member)是一个常量,list_entry()正是利用这个不变的偏移量来求得链表数据项的变量地址。

敬请高手指正。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/172103.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 简述sealed关键字_java field

    简述sealed关键字_java fieldsealed的中文意思是密封,故名思义,就是由它修饰的类或方法将不能被继承或是重写。sealed关键字:在类声明中使用sealed可防止其它类继承此类;在方法声明中使用sealed修饰符可防止扩充类重写此方法。相当于Java中的final类和final方法密封类:密封类在声明中使用sealed修饰符,这样就可以防止该类被其它类继承。如果试图将一个密封类作为其它类的基类,C#将提示出错。在哪些场合…

    2022年10月22日
  • 使用栈实现表达式求值

    使用栈实现表达式求值任何一个表达式都是由操作数,运算符,界限符组成的。操作数即是参加运算的数值或者变量,运算符则是加减乘除等组成,为简单起见,这里只实现加减乘除的运算,而常见的界限符则是左右括号和终止符。在运算过程中,要判断两个先后出现的运算符之间的优先顺序。为了实现算法,设置两个工作栈:用于存储运算符的栈opter,以及用于存储操作数及中间结果的栈opval。算法基本思想如下:(1)首先将操作数栈opv

  • 手机桌面锁屏时钟_手机锁屏时钟软件

    手机桌面锁屏时钟_手机锁屏时钟软件桌面锁屏时钟是一款专门为用户提供手机便捷的学习生活音乐时钟管理的软件,用户可以在线设置非常简约的界面,自带了时间和日期,查看天气,温度和降噪音播放音乐的功能,利用经典的动态翻页,可以选择丰富的皮肤,让自己体验非常丰富的桌面锁屏,提供了强大的工具箱,可以在线选择闹钟和计时器,辅助自己学习生活,在线能够播放舒适的音乐背景,支持用户在手机上面自己自由定义设置锁屏桌面,可以调节时钟和日期的样式。桌面锁屏时…

  • plc中scl语言_plc中scr是什么意思

    plc中scl语言_plc中scr是什么意思本人小白一个,只是刚刚学习scl,想与大家分享一下,如果您是大佬,请勿喷。在我的理解,PLC就像单片机,而scl语言就像C语言,例如scl语言里的=就是C里的==如果学过C将会事半功倍,SCL语言学习并不需要什么网上视频,譬如我在某宝上买了一个视频,发现他讲的没有什么用处你只要会按F1,都能把他讲的找到,西门子的帮助功能十分强大,你可以找到基础的+,-,*,/,=,:=等等,他都会教给你使用及符…

  • linux修改系统时间命令_centos设置系统时间

    linux修改系统时间命令_centos设置系统时间linux设置系统时间同步到硬件时钟#date日期%Y2017%y17#后两位%m06%d12%H-%M-%S%F#2017-06-19%T#15:48:22date

  • python3中urlopen_Python3 urlopen()用法示例[通俗易懂]

    对python这个高级语言感兴趣的小伙伴,下面一起跟随编程之家jb51.cc的小编两巴掌来看看吧!一.简介urllib.request.urlopen()函数用于实现对目标url的访问。函数原型如下:urllib.request.urlopen(url,data=None,[timeout,]*,cafile=None,capath=None,cadefault=False,context=N…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号