offsetof 说明

在c标准的stddef.h中有一个获取c/c++结构或者类成员偏移量的宏offsetof,具体定义如下:

 #ifdef  _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&reinterpret_cast<const volatile char&>((((s *)0)->m)) )
#else
#define offsetof(s,m)   (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
#endif#else#ifdef  _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m)   (size_t)&(((s *)0)->m)
#endif

参数说明:

s: 结构体类型

m: 是结构体数据成员名称

思想就是将地址0强制转换成类型s,然后通过求结构体数据成员地址的方式,获取偏移量。

C程序的例子:


#include <stdio.h>
struct A{int a1; int a2;
};
main()
{struct A a, *pa;a.a1=22;a.a2=33;pa = &a; // Print the address of the data member of variable aprintf("By variable a &a(%p) &a.a1(%p) &a.a2(%p) \n", &a, &a.a1, &a.a2);// Print the address of the data member of the pointer pa. The pa point to the variable a.printf("By pointer pa &a(%p) &pa->a1(0x%lx) &pa->a2(0x%lx)\n", &a, (size_t)&pa->a1, (size_t)&pa->a2);struct A *s=(struct A*)0;// Print the address of the data member of the pointer s. The s point to 0.printf("By pointer s &s->a1(%ld) &s->a2(%ld)\n", (size_t)&s->a1, (size_t)&s->a2);// Change s point to 100.s = (struct A*)100;printf("By pointer s &s->a1(%ld) &s->a2(%ld)\n", (size_t)&s->a1, (size_t)&s->a2);// First deference the pointer s, then get the address of the data memeber. printf("By pointer s &(*s).a1(%ld) &(*s).a2(%ld)\n", (size_t)&(*s).a1, (size_t)&(*s).a2);// Dangerous? Deference the pointer s, the get value of the data member.// printf("By pointer s (*s).a1(%d) (*s).a2(%d)\n", (*s).a1, (*s).a2);
}

执行结果:

By variable a &a(0x7fff5e0bae60) &a.a1(0x7fff5e0bae60) &a.a2(0x7fff5e0bae64)

By pointer pa &a(0x7fff5e0bae60) &pa->a1(0x7fff5e0bae60) &pa->a2(0x7fff5e0bae64)

By pointer s &s->a1(0) &s->a2(4)

By pointer s &s->a1(100) &s->a2(104)

By pointer s &(*s).a1(100) &(*s).a2(104)

从执行结果可以得出这样的结论:

1、对结构体数据成员取地址,是以结构体变量首地址为基础的。

2、获取数据成员的地址运算是指针运算,不管地址是合法的还是非法的,都可以。
因为这只是地址运算,不会操作地址所指向的 内存。

3、如果我们把地址设为0,那么对数据成员取地址,就可以获取偏移量了。

C++例子

我们将上面的例子简单修改一下,增加一个virtual 成员函数,看看效果:

#include <stdio.h>
struct A{virtual ~A(){}int a1; int a2;
};
main()
{struct A a, *pa;a.a1=22;a.a2=33;pa = &a; // Print the address of the data member of variable aprintf("By variable a &a(%p) &a.a1(%p) &a.a2(%p) \n", &a, &a.a1, &a.a2);// Print the address of the data member of the pointer pa. The pa point to the variable a.printf("By pointer pa &a(%p) &pa->a1(0x%lx) &pa->a2(0x%lx)\n", &a, (size_t)&pa->a1, (size_t)&pa->a2);struct A *s=(struct A*)0;// Print the address of the data member of the pointer s. The s point to 0.printf("By pointer s &s->a1(%ld) &s->a2(%ld)\n", (size_t)&s->a1, (size_t)&s->a2);// Change s point to 100.s = (struct A*)100;printf("By pointer s &s->a1(%ld) &s->a2(%ld)\n", (size_t)&s->a1, (size_t)&s->a2);// First deference the pointer s, then get the address of the data memeber. printf("By pointer s &(*s).a1(%ld) &(*s).a2(%ld)\n", (size_t)&(*s).a1, (size_t)&(*s).a2);// Dangerous? Deference the pointer s, the get value of the data member.// printf("By pointer s (*s).a1(%d) (*s).a2(%d)\n", (*s).a1, (*s).a2);
}

执行结果:

By variable a &a(0x7fffd686f520) &a.a1(0x7fffd686f528) &a.a2(0x7fffd686f52c)

By pointer pa &a(0x7fffd686f520) &pa->a1(0x7fffd686f528) &pa->a2(0x7fffd686f52c)

By pointer s &s->a1(8) &s->a2(12)

By pointer s &s->a1(108) &s->a2(112)

By pointer s &(*s).a1(108) &(*s).a2(112)

首个数据成员的偏移量是8,原因是因为有了vptr指针。

stddef offsetof相关推荐

  1. offsetof使用小结

    先上例子 #include <stdio.h> #include <stdlib.h>/* offsetof example */ #include <stddef.h& ...

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

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

  3. c语言 offsetof函数,C 库宏 - offsetof()函数

    宏offsetof 标准库stddef.h 定义 size_t offsetof(type, member); 分析 C 库宏 offsetof(type, member) 会生成一个类型为 size ...

  4. container_of 和 offsetof 宏详解

    在linux内核链表中,会遇到两个宏. 在include/linux/stddef.h中,有这样的定义 #define offsetof(TYPE, MEMBER) ((size_t) &(( ...

  5. Linux / offsetof 和 container_of

    @time 2019-07-10 @author Ruo_Xiao @revision linux 2.6.11 1. offsetof (1)原型 /** @member TYPE : 结构体原型. ...

  6. 自己实现了一个C语言例程,加深对宏、大小端、typeof宏、offsetof宏、指针变量、结构体、联合体的理解

    如题所述,最近时间在复习C语言.自己实现了一个C语言例程,以加深对宏.大小端.typeof宏.offsetof宏.指针变量.结构体.联合体的理解.关于细分知识后续有空再填充- swap宏的使用: 对应 ...

  7. C库宏-offsetof()

    在项目开发过程中,发现了offsetof()函数,随即查询了此函数,摘录如下: C库宏 - offsetof() 描述 C库宏offsetof(type, member-designator)会生成一 ...

  8. 使用offsetof对结构体指针偏移操作

    题目来自于COMP20003 Tutorial 2: Program m ing Challenge 2.2 The technology stack at Hidebound Inc. uses a ...

  9. sizeof与offsetof有关的结构体详解

    sizeof与offsetof在程序中经常遇到,但在面试中其应用使得许多小伙伴吃闭门羹,被面试官问得哑口无言.接下来对两者的应用做详细介绍. 关于sizeof 定义 sizeof乃C/C++中的一个操 ...

最新文章

  1. 为x86 CPU自动调度神经网络
  2. mysql 数据索引使用_mysql数据库正确建立索引及使用
  3. eclipse中设置python的版本
  4. 数据结构和算法分析:第四章 树
  5. 读书笔记∣世界是数字的
  6. 自动化通讯协定——现场总线
  7. 自动化测试基础篇--Selenium等待时间
  8. Centos系统新建文本文档.txt
  9. winrar加密分析
  10. 用foobar将ape转换为mp3格式
  11. 怎样找回通讯录的联系人号码?手机通信录联系人恢复教程推荐
  12. 2021玉林芳草中学高考成绩查询,「分数线」2020年成都玉林中学招生录取分数线...
  13. ps 修改透明图片上的文字,修改图片大小,导出PNG
  14. 计蒜客T3054数列
  15. C++详细学习笔记(二)
  16. 中国奥运在线流量的数据所做的总结性结案报告
  17. Prometheus 简介
  18. 你了解视频 API 吗?
  19. mysql数据库数据的删除与恢复
  20. 2017中国工业互联网大会召开

热门文章

  1. 计算机专业应聘人事专员,hr人事专员面试经验 - 共203条真实hr人事专员面试经验分享 - 职业圈...
  2. 2021年中式烹调师(高级)考试总结及中式烹调师(高级)模拟考试
  3. Scriptlet的3种模式
  4. 爬虫实战——网页抓取及信息提取
  5. mysqltruncate函数
  6. 冰箱“扩容”的战事,在今夏格外猛烈
  7. 英雄联盟的小案例理解Java中如何实现OCP原则
  8. Qt5官方demo解析集13——Qt Quick Particles Examples - Image Particles
  9. button 设置圆角
  10. 信噪比概念及噪声来源