【问题标题】:Complicated C cast explanation复杂的 C 类型转换解释
【发布时间】:2009-11-11 14:33:50
【问题描述】:

我想弄清楚下面的 C 代码是做什么的?

((void(*)())buf)();

其中 'buf' 是一个 char 数组。

【问题讨论】:

  • 寻找一个名为“cdecl”的程序。下载它。将声明粘贴到其中。开悟吧。
  • @Paul:我会尝试并希望它不会杀死我的机器!
  • 此代码可能合理地出现在 JIT 中,或者在动态链接器/加载器的操作系统中。正如其他人所说,这是可怕的东西,但前提是您在典型的应用程序中遇到过它。在适当的地方,它不是可怕的东西,只是困难的东西。

标签: c casting void


【解决方案1】:

让我们一步一步来。

void(*)()

这是一个指向函数的指针,该函数接受未指定的参数并且没有返回值。

(void(*)())buf

简单地将 buf 转换为这个函数指针类型。最后,

((void(*)())buf)();

调用这个函数。

所以整个语句是“将 buf 解释为指向不带参数的 void 函数的指针,并调用该函数。”

【讨论】:

  • 将字符缓冲区转换为函数并调用它是邪恶的。这要么是尝试自我修改代码,要么是恶意企图进行某种利用。无论哪种方式,都要不惜一切代价避免它。
  • 如果我错了,请纠正我,但不是将指针的值(数组的地址)视为函数,而不是数组的内容吗? "interpret the value in buf" 听起来有点像您在说内容被解释为指向函数的指针。
  • @Paul:更可能是代码生成,但你的抱怨仍然适用,当然。 :)
  • 请注意,C 不保证数据指针与函数指针具有相同的大小。
  • @vonolsson:除了指针大小之外,C 不保证分配在堆栈或堆上的内存是可执行的。此代码应仅出现在 JIT 或等效代码中,并且必须是特定于平台的。假设 buf 刚刚被机器指令填充,那么在引用的 cast-and-call 之前的那行应该是某种特定于平台的操作来刷新 icache。
【解决方案2】:

它将buf 转换为void(*)() 类型的函数指针(一个不返回任何内容/void 并采用未指定参数的函数)并调用它。

ANSI 标准实际上不允许将普通数据指针转换为函数指针,但您的平台可能允许。

【讨论】:

  • 你怎么能把数组转换成函数指针??有文章解释吗?
  • 指针只是字节的集合,就像任何其他值一样(因此可以在 C 中表示为字符数组)。您可能会发现程序的其他地方与此相反:char *buf = (char *)function; 或类似的东西。
  • 你可以这样做,因为它是 C——你可以做任何你想做的事。这是一个糟糕的主意,但你可以做到。
  • 我的意思是它不能保证工作。这是 ANSI 中未定义的行为:在哈佛架构上,您的程序内存和数据内存在物理上是分开的,因此从 char* 转换为 void(*)() 没有意义。
  • 即使在冯诺依曼体系结构上,如果使用分段,那么具有相同值的数据指针和函数指针可能指向不同的内存(MS-DOS“小”内存模型是真实的这个例子)。
【解决方案3】:

当我遇到令人难以置信的声明时,我倾向于使用“cdecl”命令。示例:

[me@machine]$ cdecl
Type `help' or `?' for help
cdecl> explain (void(*)())buf
cast buf into pointer to function returning void

虽然在某些情况下我确实希望有一个工具可以解释“cdecl”的输出:/

【讨论】:

    【解决方案4】:

    这会将buf 转换为void (*)() 类型,这是一个指向函数的指针,该函数接受未指定的参数并且不返回任何内容。然后它调用该地址(最右边的两个括号)处的函数。

    【讨论】:

      【解决方案5】:
      ((void(*)())buf)(); \------------/ 将 `buf` 转换为 \---------/ type: 指向函数的指针,接受一个固定但 未指定数量的参数和 返回无效 \----------------/ 并称其为“函数”

      【讨论】:

      • +1 您对未指定数量的参数是正确的。如果你用一个例子进行了澄清,你可能会更加欣赏你的洞察力:)
      【解决方案6】:

      它将buf 转换为一个函数指针,该指针接受未指定的参数并调用它。

      【讨论】:

        【解决方案7】:

        我猜在许多情况下,它会使机器崩溃。 否则,它将数组视为指向返回 void 并调用它的函数的指针。

        【讨论】:

          【解决方案8】:

          如果我没记错的话,你可能会发现“专家 c 编程”是一本不错的读物——解压这类东西在其中一章中。我已经很久没有读过了,但我记得当时我认为这是值得的。 http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298

          【讨论】:

            【解决方案9】:

            有一个在线版本的“cdecl”工具,lsc 提到它可能对你有用:http://www.cdecl.org/

            【讨论】:

              【解决方案10】:

              调用函数指针。该函数没有参数。

              Function Pointer - Wikipedia

              【讨论】:

              • 该函数没有(给出)参数。函数类型有未指定的参数。
              • 当然,鉴于其他答案,我将保持原样。
              猜你喜欢
              • 2021-08-31
              • 1970-01-01
              • 2014-08-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-08-14
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多