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

C 使用未知数量的参数通过引用调用函数,c,pointers,function-pointers,C,Pointers,Function Pointers,为了仅仅通过一个名字来调用函数,我想出了这段代码。这目前有效,但我不确定这是否是未定义的行为。谁能解释一下,也许能帮我想出一个更好的解决办法 #include <stdio.h> typedef void (*FunctionCallback)(); void first(char *str); void second(int , int); FunctionCallback function[] = {&first, &second}; void first(ch

为了仅仅通过一个名字来调用函数,我想出了这段代码。这目前有效,但我不确定这是否是未定义的行为。谁能解释一下,也许能帮我想出一个更好的解决办法

#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;
}
#包括
typedef void(*FunctionCallback)();
首先无效(char*str);
无效秒(int,int);
函数回调函数[]={&first,&second};
先空(char*str)
{
printf(“第一个:%s\n”,str);
}
无效秒(整数x,整数y)
{
int答案;
答案=x+y;
printf(“第二个:%d\n”,答案);
}
int main()
{
功能[0](“工作”);
函数[1](6,5);
返回0;
}

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


请注意,此技术不适用于可变函数或具有非“自提升”参数的函数,例如类型为
short
float

,如果小心,这应该是可以的。我认为UB可能只是在
first
的情况下,它期望
char*
,但它已经传递了
const char*
。也许在某个平台上,编译器将
constchar*
东西放在某个奇怪的地方,可写内存的寻址方式不同。但这是异国情调,假设

总之,要清楚,在C中:

typedef void (*FunctionCallback)();
是指向没有参数列表的函数的指针类型。正如mafso所说,它是兼容的

typedef void (*FunctionCallback)(void);
将表示指向期望零参数的函数的指针。这将仅与采用零参数的其他函数兼容。(注意,它与C++不同,其中<代码> FunE()/Cuth>与Fund(Value:Value:/Cuff>)在

中相同。 编辑:

我想进一步强调的是,每一次都需要正确的论据。同时,编译器不能帮你,所以,嗯,祝你好运


我可以想象一个想要变得聪明的编译器,看到你从来没有存储过任何
fun(const char*)
的地址,并使用它来优化你的代码,从而删除了对
第一个

相关标准引用(n1570,C99)第6.7.6.3/15节的调用:“如果一种类型具有参数类型列表,而另一种类型由包含(可能为空)标识符列表的函数定义指定,则两者的参数数量应一致,并且每个原型参数的类型应与将默认参数提升到相应标识符的类型所产生的类型兼容。”(请注意。)此外,fwiw、指向函数的指针可以是双向强制转换的,因此您可以通过显式强制转换来实现
关于旧式函数:要查看对比,请尝试使用以下代码进行编译:
typedef void(*FunctionCallback)(void);
,第一段的所有内容都有点误导,一个
char*
可以指向只读内存(但您不能写入,检查这一点是您的责任),和
const char*
可以指向可写内存。但这一点仍然成立,理论上它们可以以不同的方式传递给函数。+1例如,使用这种设置的代码很容易变得未定义。它可以指向只读内存,但这不是一个要求。也许,ABI使用不同的方式传递这些参数在所有情况下,如果使用
const char*
调用
func(char*)
,编译器都需要做一些额外的工作,以使其看起来工作顺利。好吧,只要程序员不向编译器隐藏它。。。