【问题标题】:C++ vararg function pointerC++ 可变参数函数指针
【发布时间】:2011-10-13 00:20:31
【问题描述】:

以下是否会导致明确定义的行为?也就是说,如果您将非可变参数函数 f 转换为可变参数函数 g 并使用 f 期望的参数调用 g,那么行为是否与使用这些参数调用 f 的行为匹配?

class Base {};

class Derived1 : public Base {
public:
    int getInt1() {return 1;}
};

class Derived2 : public Base {
public:
    int getInt2() {return 2;}
};

typedef int (*vfunc)(...);

int foo (vfunc f) {
    Derived1 d1;
    Derived2 d2;
    return f(&d1, &d2);
}

int bar (Derived1 * p1, Derived2 * p2) {
    return p1->getInt1() + p2->getInt2();
}

int main (int argc, char ** argv) {
    return foo((vfunc)bar); // Is this program guaranteed to return 3?
}

更新

有没有什么方法可以让程序得到很好的定义,即使使用专有关键字?比如做一些这里提到的__cdecl之类的东西:

http://msdn.microsoft.com/en-us/library/984x0h58%28v=vs.80%29.aspx

我的最终目标是有一个matcher 函数尝试匹配 X 指针列表。 matcher 函数接受一个谓词(不一定是一个函数......可能是一个列表)并接受一个函数,它将把匹配的结果传递给它。传递给它的回调函数采用与匹配的谓词相同的参数类型和数量。

【问题讨论】:

  • 我相信并期望答案是这是未定义的行为。
  • 当您说“专有关键字”时,您是什么意思?您的目标是什么编译器(以及版本和设置)?您是否愿意接受其他更好的解决方案(例如 std::function)?
  • Visual Studio 中的 __cdecl 之类的东西。我也愿意接受其他解决方案。

标签: c++ variadic-functions


【解决方案1】:

不,行为未定义,根据 C++11 5.2.11/6 (reinterpret_cast):

通过指向与函数定义中使用的类型不同的函数类型的指针调用函数的效果是未定义的。

bar 的类型是int(Derived1*, Derived2*)f(进行调用的表达式)指向的函数类型是int(...)。两者不相同,因此行为未定义。

【讨论】:

  • 您能解释一下示例中使用的函数的语言链接吗?
  • @K-ballo:抱歉;复制和粘贴是我遇到麻烦的技能。我已经更正了引用。
【解决方案2】:

我很确定答案是“不”。

例如,在 Visual C++ 中,可变参数函数的调用约定与普通函数不同(使用 /Gz 时)。

调用约定决定生成什么调用前和调用后汇编代码,您不能安全地将两者混合使用。

【讨论】:

  • 如果两者都指定调用约定为cdecl 会怎样?
  • @K-ballo:你可能会很幸运,但这取决于实现。我不相信 C++ 中有任何规则说编译器必须为您提供一种自己指定调用约定的方法。事实上,C++ 标准很少提及调用约定。 (这意味着假设最坏的情况 :)
猜你喜欢
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-30
  • 2022-12-11
  • 2015-09-22
  • 2020-10-25
  • 2016-09-07
相关资源
最近更新 更多