【问题标题】:c++ - offsetof function, why is it possible to pass just the member namec++ - offsetof函数,为什么可以只传递成员名
【发布时间】:2020-06-28 14:30:14
【问题描述】:

当我定义这样的结构时:

struct abc{
 int member1;
 int arr_member1;
 std::vector<int> mVector;
}

并且想要创建一个arr_member 变量,我必须这样做:

abc x;
x.member1=3;
x.arr_member1= ...

//some more code  

但我不能这样做:

arr_member1 a = //some code  

其中 a 应该是一个由 5 个元素组成的 int 数组的变量。

但是,我怎样才能为 offsetof() 函数做到这一点:

offsetof(abc, arr_member1)  

我可以理解abc 指的是一个结构类型,但从技术上讲,arr_member 是什么?这叫什么?指针、类型、成员类型?这个宏扩展成什么,编译器如何编译它?

我的意思是,arr_member 不是字符串或关键字,它不是由语言或类定义的任何数据类型,那么编译器如何确定它不仅仅是一些随机的东西?

如果可能,请说明编译器如何实现特定的宏?

【问题讨论】:

  • arr_member1 a 没有任何意义,因为arr_member1 没有命名类型。你真正想要实现什么,offsetof 与它有什么关系?
  • 你确定你不是在寻找类似decltype的东西吗?
  • offsetof 不能在 c++ 中实现(它是魔法,标准只是说明了它应该做什么)。如果您要询问特定编译器如何实现它,请澄清问题并添加适当的标记。
  • offsetof 是一个宏。它使用其参数执行一些文本替换,最终生成编译器可以理解的有效代码。
  • 我不确定我是否完全理解这种区别。 Name lookup 是编译器根据 C++ 语言标准规定的规则执行的过程。这是一个将给定名称的使用与该名称的先前声明相匹配的过程,以确定该名称在给定上下文中所指的实体。

标签: c++


【解决方案1】:

我不明白你的大部分问题,但标题:

offsetof函数,为什么只能传成员名

offsetof(abc, arr_member1)  

来自cppreference

offsetof 不能在标准 C++ 中实现,需要编译器支持

它不能在标准 C++ 中实现的原因是因为在类 arr_member1 之外没有实体。它只是成员的名字。编译器知道类成员的名称,但arr_memer1 是(在类之外)您无能为力的。 C++ 有指向成员的指针,但offsetof 没有将指向成员的指针作为参数。它是一个讨厌的宏,它不是基于 C++ 的特性,而是依赖于可以访问自己实现的编译器。

【讨论】:

  • 能告诉我编译器如何实现这个吗?
  • 如果您点击答案中的链接,您可以查看 2 个不同实现的链接。
  • @cigien ,是的,它提供了指向 gccllvm 实现的链接,但它们提供了类似:#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) 的内容,除非我们能以某种方式深入研究吗?
  • 当然要找__builtin_offsetof的定义,等等……
【解决方案2】:

因为offsetof是一个宏,所以在宏定义里面,字段名会和你传入的类型一起使用。看起来是这样的:

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

来源:https://en.wikipedia.org/wiki/Offsetof

【讨论】:

  • 需要注意的是,这个实现:1.依赖UB,2.不是constexpr,不像标准的那样。
  • 补充一下这是伪代码而不是合法的 C++ 会很有用。
  • @HolyBlackCat ,什么是 UB?
  • @juztcode UB 是未定义的行为。这意味着您不允许这样做。在这种情况下,至少在 -> 调用 UB 期间发生的空指针取消引用。您不得取消引用空指针。 C++ 语言并不能保证此时会发生什么。因此,任何事情都可能发生。如果你幸运的话,你的程序会崩溃。如果你不走运,它会继续,将垃圾写入数据库,一个月后你将不得不向愤怒的客户解释为什么他的所有数据都已损坏。以目前的形式,这不是一个有效的答案。
  • 嗯....是的,我想是的,但是答案很明确地指出了我想问的问题,所以我将其标记为答案,尽管@idclev 的答案也很好,我已经建议回答者编辑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-11
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 2016-09-11
  • 2015-04-02
  • 1970-01-01
相关资源
最近更新 更多