__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()正是利用这个不变的偏移量来求得链表数据项的变量地址。

敬请高手指正。

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql的innodb引擎默认事务隔离级别_mysql中事务的隔离级别

    mysql的innodb引擎默认事务隔离级别_mysql中事务的隔离级别这里不再重复READ_UNCOMMITTED,READ_COMMITTED,REAPEATED_READ,SERIALIZABLE这几种标准事务隔离级别的关系,网上资料一大把。很多朋友可能会有疑惑,如果Spring事务可以设置隔离级别,而数据库也可以设置默认隔离级别,那他们到底是怎样的关系呢?直接说结论:-Spring会在事务开始时,根据你程序中设置的隔离级别,调整数据库隔离级别与…

    2022年10月9日
    0
  • Excel VBA编程教程(基础一)

    Excel VBA编程教程(基础一)VBA介绍VisualBasicforApplications(VBA)是VisualBasic的一种宏语言,是微软开发出来在其桌面应用程序中执行通用的自动化(OLE)任务的编程语言。主要能用来扩展Windows的应用程序功能,特别是MicrosoftOffice软件。说简单点,VBA是运行在MicrosoftOffice软件之上,可以用来编写非软件自带的功能的编程语言。Office软件提供丰富的功能接口,VBA可以调用它们,实现自定义的需求。基本上,能用鼠标和键盘能做的

    2022年4月29日
    2.1K
  • redis 乐观锁_什么时候用乐观锁

    redis 乐观锁_什么时候用乐观锁文章目录GeospatialHyperloglogBitmapsRedis事务悲观锁和乐观锁JedisSpringboot继承RedisGeospatial存储地理位置的数据结构应用场景朋友的定位,附近的人,打车距离计算Geospatial底层使用的是Zset127.0.0.1:6379> geoadd city 116.23 40.22 beijing 添加一个数据127.0.0.1:6379> geoadd city 121.47 31.23 shanghai 118.77

    2022年8月9日
    3
  • windows上安装redis并安装php5.6的redis扩展

    windows上安装redis并安装php5.6的redis扩展

    2021年10月16日
    56
  • MySQL事务表和非事务表

    MySQL事务表和非事务表

    2022年2月10日
    42
  • python中for循环的用法1+2+3…+50的和_python结束for循环

    python中for循环的用法1+2+3…+50的和_python结束for循环1.一般格式range(stop)#0~stop-1range(start,stop)#start~stop-1range(start,stop,step)#start~stop-1,step表示步长注:Python中break,continue的用法与C中一致2.在enumerate中的用法enumerate()(单词意思是枚举的意思)是python中的内置函数,enumera

    2022年8月12日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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