使用未知数量的参数通过引用调用函数

Calling functions by reference with unknown amount of parameters

为了仅通过名称调用函数,我想出了这段代码。这目前有效,但我不确定它是否是未定义的行为。任何人都可以对此有所了解,也许可以帮助我提出更好的解决方案。

#include <stdio.h>
typedef void (*FunctionCallback)();
void first(char *str);
void second(int , int);
FunctionCallback function[] = {&first, &second};

void first(char *str )
{
    printf( "First: %s\n", str );
}

void second(int x, int y)
{
    int answer;
    answer = x +y;
    printf("Second: %d\n", answer);
}

int main()
{
    function[0]("Working");
    function[1](6, 5);

    return 0;
}

代码有效,但使用了在 C89 中标记为过时的旧式声明。用于调用函数的函数指针和被调用函数的类型必须兼容,并且传递的参数类型必须与定义的类型匹配。对于显示的代码,两者都是正确的。

请注意,此技术不适用于可变参数函数或参数不是 "self-promoting" 的函数,例如 shortfloat 类型的函数。

这应该没问题,如果你小心点。我认为 UB 可能仅在 first 的情况下,它期望 char*,但已将 const char* 传递给它。也许在某些平台上,编译器将 const char* 的东西放在一些奇怪的地方,并且可写内存的地址不同。但那是异国情调的,假设的。

无论如何,要清楚,在 C:

typedef void (*FunctionCallback)();

是一种指向没有参数列表的函数的指针。所以它是兼容的,正如mafso所说。

typedef void (*FunctionCallback)(void);

表示指向需要零参数的函数的指针。这只会与其他采用零参数的函数兼容。 (注意它不同于 C++,其中 fun() 与 C 中的 fun(void) 相同)

编辑:

我要强调的是,每次仍然需要正确地论证。与此同时,编译器无法帮助你,所以,嗯,祝你好运。

我可以想象一个编译器,想要变得聪明,看到你永远不会存储任何 fun(const char*) 的地址,并使用它来优化你的代码,从而删除对 first 的调用.