【问题标题】:Function pointers with different return types具有不同返回类型的函数指针
【发布时间】:2014-05-12 00:10:54
【问题描述】:

这是正确的代码吗?

class SomeClass;

SomeClass* createSomeClass(); // just returns new SomeClass
void* (*createFuncPtr)();

int main()
{
    createFuncPtr= (void* (*)()) &createSomeClass;
    SomeClass* instance = (SomeClass*)createFuncPtr();
}

C 标准说:

768 如果转换后的指针用于调用类型为 与指向的类型不兼容,行为未定义。

在这种情况下,函数类型是否兼容?或者如果我想避免蚂蚁的麻烦,我是否必须在调用它之前重新转换函数指针?

SomeClass* instance = ((SomeClass* (*)())createFuncPtr)();

谢谢!

编辑:是的,它包含 C++ 代码,但如果它只是 C,我的问题仍然有效,请留下 C 标记。

【问题讨论】:

  • 你想要完成什么?
  • 刚刚得到该特定问题的答案;)

标签: c++ c


【解决方案1】:

来自 C99 标准第 6.7.5.1 节第 2 段:

对于要兼容的两个指针类型,两者都应具有相同的限定,并且都应是指向兼容类型的指针。

在您的情况下,函数指针不兼容,因为返回值不兼容。所以,是的,你必须在调用指向的函数之前进行回滚。

【讨论】:

  • 感谢 Filipe,这是有道理的。但是,什么是两种兼容类型呢?你有这个函数指针转换可以工作的兼容类型的例子吗?
  • @JeremyLaumon 底线是voidsomeClass 不是兼容的类型,因为它们是不同的类型。类型兼容的规则比较长,可以看一下 C99 的 6.2.7 节。
【解决方案2】:

您需要将其转换回正确的类型,否则您很可能会损坏您的堆栈。在此处查看更详细且有些有趣的描述:Old New Thing: A function pointer cast is a bug waiting to happen

编辑:由于无论如何您都需要将其转换为正确的类型,因此您也可以使用 void 指针(编辑:由于 void 指针的大小可能更小,因此不起作用,这要归功于Filipe)而不是错误的函数指针来存储指针,以避免不小心调用错误。或者使用正确的函数指针类型。或者一个 std::function 对象,取决于你的目标。

【讨论】:

  • @Filipe 它在哪里这么说,为什么这不起作用?具有不同大小的函数指针和 void 指针的疯狂平台?
  • @nwp 是的,这是一个很好的例子。该标准不保证 void 指针和函数指针的大小相同。它也不保证您可以互换使用它们。即使它们的大小相同,由于数据执行保护,您也不应该混合数据和代码指针。
  • @Filipe 我不明白您评论中的数据执行保护部分。根据我的理解,指针在哪里并不重要,只在指针指向的位置重要,因此将函数指针放在指向常规函数的堆栈上必须始终有效。所以我看不出 void 指针和函数指针在数据执行保护方面的区别。我错过了什么吗?
  • @nwp 当然,指针的存储位置并不重要——我对 DEP 的评论是为了强调混合数据和代码的想法是多么糟糕,因为它可能会导致神秘的错误。可能是 void 指针和函数指针的大小确实相同,并且定义了两者之间的转换(如 POSIX 中的情况),但就 C 标准而言,不能假设这一点。 SO中有很多关于此的问题,例如参见stackoverflow.com/questions/12358843/…
猜你喜欢
  • 2015-04-18
  • 1970-01-01
  • 1970-01-01
  • 2016-09-13
  • 1970-01-01
  • 1970-01-01
  • 2014-01-04
  • 1970-01-01
  • 2018-12-08
相关资源
最近更新 更多