【问题标题】:Can I pass this through a function?我可以通过函数传递它吗?
【发布时间】:2014-06-16 06:25:54
【问题描述】:

我正在包装一个脚本库,并且这个宏存在。

#define asOFFSET(s,m) ((size_t)(&reinterpret_cast<s*>(100000)->m)-100000)

m 是什么类型?它有例子:

struct MyStruct
{
  int a;
};

asOFFSET(MyStruct,a)

我想把它放到一个函数中。

【问题讨论】:

    标签: c++ templates types


    【解决方案1】:

    脚本库(最有可能)使用宏来找出类成员的内部布局,而无需对其类型、体系结构或继承模型进行假设。 (一个简单的例子是discussed here)。

    对于大多数 C++ 程序,理想情况下根本不需要这些信息(内存布局)。但是如果您确实需要它(例如,如果您正在编写分析器/调试器),您最好按原样保留这个宏(或者最好用 offsetof 替换它在代码中的用法,就像 Michael Anderson指出。)有compiler-specific implementations

    1. 更高效
    2. 不太可能被报告为执行无效操作(例如,在使用 Valgrind 等工具时取消引用无效内存地址)。

    使用这些等效选项,理想情况下应该不需要手纺替代品或包装纸。

    【讨论】:

      【解决方案2】:

      这是offsetof 宏的实现。 ms 的任何成员。它没有对应的 C 或 C++ 类型 - 但与 pointer to member 的概念密切相关。

      【讨论】:

      • 请注意,这很糟糕。这个有未定义的行为; offsetof 根据定义没有。
      • @MSalters 我怀疑是这样 - 但不想冒犯任何人;)
      【解决方案3】:

      宏的目的是确定,给定结构的any名称和该结构的成员的any名称,在内存中的距离 从结构的任意实例的开头,以及该成员在同一实例中的位置。

      m 没有“类型”,s 也没有。 当您使用宏时,“类型”的整个概念就会消失。这东西简直不是C++;它基本上是一种完全独立的语言,用于就地编辑 C++ 代码。当预处理器运行时,asOFFSET(MyStruct, a) 将在编译器开始工作之前被文本替换 ((size_t)(&amp;reinterpret_cast&lt;MyStruct*&gt;(100000)-&gt;a)-100000)

      ((size_t)(&amp;reinterpret_cast&lt;MyStruct*&gt;(100000)-&gt;a)-100000) 旨在评估为 0,因为 MyStruct 实例的 a 成员出现在每个实例的开头。我实际上并不是 100% 确定这是符合规范的合法行为,但意图如下:

      • 通过将数字100000 视为指向MyStruct 的指针,假设在内存位置100000 存在MyStruct 的实例。

      • 获取这个假结构的a成员在内存中的地址,然后再次减去100000。这给了我们从假结构的开头到该假结构的指定成员的距离。

      • 将该数值转换回size_t(用于测量内存分配的数值类型,无符号整数类型)。

      【讨论】:

      • 如果我运行这个:struct MyStruct {/*int fake1;*/ long fake2; int a;}; `printf("%d\n",(int)asOFFSET(MyStruct,a));` 的结果将是8。如果结构为:struct MyStruct {int fake1; long fake2; int a;};,则结果将为16。为什么?
      • 您已将步骤 2 和 3 颠倒过来。如果你在强制转换之前减去 100000,那将是一个指针减法。
      猜你喜欢
      • 2020-01-19
      • 1970-01-01
      • 1970-01-01
      • 2011-02-20
      • 2020-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-14
      相关资源
      最近更新 更多