【问题标题】:reinterpret_cast to function pointerreinterpret_cast 到函数指针
【发布时间】:2014-08-05 04:05:53
【问题描述】:

这是我为reinterpret_cast<T> 的实验而编写的代码

#include <iostream>
#include <cstdlib>

using std::cout;
using std::endl;

int foo()
{
    cout << "foo" << endl;
    return 0;
}

void (*bar)();
int main()
{

    bar = reinterpret_cast<void (*)()>(foo); //Convertion a function type to a pointer to function type
    bar(); //displays foo. Is it UB?
}

首先为什么允许这样的reinterpret_cast 转换?我认为这样的转换是不正确的。

【问题讨论】:

  • C++ 允许你以许多有趣的方式射你的脚,如果你幸运的话,编译器会给你一个警告。但是,如果您以任何方式禁用警告或错误,例如使用reinterpret_cast 将一种类型转换为另一种(可能不兼容)类型,许多人会说您应该得到您应得的。
  • @JoachimPileborg 但是 5.2.10/1 说下面列出了可以使用 reinterpret_cast 显式执行的转换。无法使用 reinterpret_cast 显式执行其他转换。 5.2.10没有这样的转换。

标签: c++ reinterpret-cast


【解决方案1】:

The standard (C++11 §5.2.10/6) 说

指向函数的指针可以显式转换为指向不同类型函数的指针。通过指向与函数定义中使用的类型不同的函数类型的指针调用函数的效果是未定义的。除了将“指向 T1 的指针”类型的纯右值转换为“指向 T2 的指针”类型(其中 T1 和 T2 是函数类型)并返回其原始类型会产生原始指针值之外,这种指针转换的结果是未指定的.

所以这是未定义的行为。

【讨论】:

  • 怎么不清楚? “指向函数的指针可以显式转换为指向不同类型函数的指针。”
  • 函数类型与指向函数类型的指针不同。
  • 很清楚。但我不会将指向函数的指针转换为另一个指向函数的指针。我将 函数类型 转换为指向函数的指针。
  • @St.Antario:是的。但是,在几乎所有上下文中,函数类型衰减为函数指针类型。这种情况与数组发生的情况非常相似。阻止函数类型 decay 的唯一上下文是一元 &amp; 运算符、sizeof 运算符和其他一些。 reinterpret_cast 也不例外,这意味着每次将函数名指定为操作数时,它都会隐式转换为函数指针类型。 IE。 reinterpret_cast&lt;&gt;(foo) 完全等同于 reinterpret_cast&lt;&gt;(&amp;foo)
  • @St.Antario 来自 §4.3/1:“函数类型 T 的左值可以转换为类型为“指向 T 的指针”的纯右值。结果是一个指向函数的指针。”
【解决方案2】:

通过转换为不同函数类型的指针正式调用是未定义的行为(根据 C++11 §5.2.10/6)。

实际上,您正在丢弃类型为int 的函数结果,该结果将在寄存器中返回。因此,当您通过强制转换的指针调用时可能发生的最糟糕的情况是,与编译器的预期相反,寄存器的值发生了变化。

另一个实际考虑:C++ 不支持函数和数据指针之间的转换,但 Posix 有效地要求转换为 void* 并返回正常工作。 C++ 限制可能是为了支持哈佛架构机器,其中指令不是通过与普通数据相同的总线和内存来检索的。但是 Posix 往返可能也适用于这种架构,除非数据地址空间远小于指令地址空间。

【讨论】:

  • 明确一点:cast 不是 UB;它被定义为从函数类型 A 转换为函数类型 B 并返回到 A 为您提供原始返回。 调用转换为不同类型后的函数是未定义的。
猜你喜欢
  • 2016-12-26
  • 2021-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-22
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
相关资源
最近更新 更多