【问题标题】:Is (int*) &var same as reinterpret_cast? [duplicate](int*) &var 和 reinterpret_cast 一样吗? [复制]
【发布时间】:2021-09-25 08:01:01
【问题描述】:

我看到一个问题What does (int*) &var mean? 有这样的代码

  char i;
  int* p = (int*) &i;

当我试图从here这部分了解时

#define     vertexmark(vx)   ((int *) (vx))[m->vertexmarkindex] 
#define     setvertexmark(vx, value)   ((int *) (vx))[m->vertexmarkindex] = value

看起来很相似,但第二段代码仍然让我感到困惑。有人可以解释一下这是怎么回事吗?

我也对现代 C++11 感到好奇,这种 C 风格的转换应该用 reinterpret_cast 代替吗?

【问题讨论】:

  • 是的,你应该改用reinterpret_cast<>,如果只是因为它可以防止你不小心把常量扔掉。
  • 您正在检查的代码来自一个旨在模拟生物功能的存储库。编写代码的目的是支持多尺度、高要求的计算。因此,它采用了专注于充分利用可执行文件的技术,而可读性和可移植性则不那么重要。本质上,它就像标准库实现的代码。由于其他合法问题,建议您最好避免在通用软件中使用大量宏和黑客攻击。但这不是“糟糕的做法”或“糟糕的代码”,都是有目的的。
  • 请参阅C-style cast,了解 C++ 对 ( new_type ) expression 的作用。 reinterpret_cast 是可能的结果之一。
  • 一般来说,C 风格的演员表比 reinterpret_cast 做的多一点——这就解释了为什么reinterpret_cast 比 C 风格演员表更受欢迎(在需要时)(在某些情况下它更安全)情况下,并且在等效的情况下,无论如何都被认为是更好的做法)。在您的第一个示例中,int *p = (int *)&i 完全等同于 int *p = reinterpret_cast<int *>(&i)。使用宏,C 风格转换和reinterpret_cast 之间可能存在差异,具体取决于m->vertexmarkindex 具有的类型(包括const 限定等)。

标签: c++ c++11 casting


【解决方案1】:

(int*) &var 和 reinterpret_cast 一样吗?

这取决于var 的类型。对于某些类型,它是相同的,而对于其他类型则不是。在示例情况下,它是相同的。

这是一个不同的例子:

const char i{};
int* p1 = (int*) &i;                  // well-formed (but dangerous)
int* p2 = reinterpret_cast<int*>(&i); // ill-formed

我也对现代 C++11 感到好奇,这种类型的 C 风格转换应该用 reinterpret_cast 替换吗?

是的,这与现代性或 C++11 无关。即使你使用的是 C++98,你也应该避免使用 C 风格的强制转换。您还应该避免使用类似的宏,而应使用函数。

【讨论】:

    【解决方案2】:

    这些是老式的 C 转换,您的 linter 规则可能会敦促您将它们转换为 reinterpret_cast 或 static_cast。

    在您编写的英文代码中,“获取 i 的地址”,它是一个指向 char 的指针,“但将其视为指向 int 的指针”。它可以防止编译器抱怨。 “我知道这是错误的,但我是故意的。”

    在您列出的#defines 中,我们不知道vx 到底是什么类型。也许它被作为void * 或其他东西传递。但他们基本上假设它是一个 int 数组,并从中获取 m-&gt;vertexmarkindex 元素。

    第二个是二传手。

    坦率地说,这对我来说听起来像是糟糕的设计,但如果不进一步挖掘,我们不确定。我想它来自一个非常古老的 C 库。

    【讨论】:

      【解决方案3】:

      看起来很相似,但第二段代码仍然让我感到困惑。有人可以解释一下这是怎么回事吗?

      让我们稍微解构一下:

      ((int *) (vx))[m->vertexmarkindex] = value
      

      (vx):宏的参数被包裹在一组括号中。这是为了允许宏与复合表达式一起使用。没有它,setvertexmark(ptr + 3, 0); 会变成((int *)ptr + 3)[m-&gt;vertexmarkindex] = 0;,这会导致错误的偏移量。

      从那时起,((int *) ptr) 只是将缓冲区重新解释为整数数组,而[m-&gt;vertexmarkindex] 只是像往常一样进行数组索引。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-29
        • 2017-06-06
        • 1970-01-01
        • 2011-11-28
        • 2020-04-10
        • 2013-02-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多