Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有不同函数返回值的函数指针数组(在C中)_C_Arrays_Function Pointers - Fatal编程技术网

具有不同函数返回值的函数指针数组(在C中)

具有不同函数返回值的函数指针数组(在C中),c,arrays,function-pointers,C,Arrays,Function Pointers,我看过一些函数指针数组的例子(例如) 在示例中,我看到数组包含具有相同类型返回值的函数(例如,所有int或所有void) 但是我想知道你能不能有一个数组来保存不同类型的函数指针 下一个代码将不会编译: #include <stdio.h> void Empty_Funcion() { ; } int funcAdd(int a, int b){ return a+b; } int main() { int ret = 0; void *array

我看过一些函数指针数组的例子(例如)

在示例中,我看到数组包含具有相同类型返回值的函数(例如,所有int或所有void)

但是我想知道你能不能有一个数组来保存不同类型的函数指针

下一个代码将不会编译:

#include <stdio.h>

void Empty_Funcion()
{
    ;
}
int funcAdd(int a, int b){
    return a+b;
}

int main()
{
    int ret = 0;

    void *array[5] = {&Empty_Funcion, &funcAdd, &Empty_Funcion, &funcAdd, &Empty_Funcion};

    ret = (*array[1])(5,7);

    printf("%d\n", ret);

    return 0;
}
#包括
void Empty_function()
{
;
}
int funcAdd(int a,int b){
返回a+b;
}
int main()
{
int-ret=0;
void*数组[5]={&Empty\u function,&funcAdd,&Empty\u function,&funcAdd,&Empty\u function};
ret=(*数组[1])(5,7);
printf(“%d\n”,ret);
返回0;
}

它说问题在于赋值ret=。。。“无效值不会被忽略,因为它应该是。”

您可以这样做:

ret = ( ( int (*)(int,int) ) array[1] )(5,7);
您需要强制转换为指向具有正确签名的函数类型的指针

但是我想知道你能不能有一个数组来保存不同类型的函数指针

如中所述,代码不起作用,因为数组打算声明包含指向返回
void
的函数的指针,但随后尝试将其作为指向返回
int
的函数的指针调用。这些类型不兼容,因此需要显式转换。并且,如ISO C99标准第6.3.2.3/8节所述,允许将函数指针转换为不同的函数指针类型,然后再转换回:

指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再转换回来;结果应与原始指针进行比较。如果使用转换的指针调用类型与指向类型不兼容的函数,则行为未定义

尽管如此,我认为这样做没有任何意义。函数指针强制转换是静态强制转换(编译器已知的强制转换),而不是动态强制转换,因此必须手动跟踪数组中哪些元素的类型为
void(*)(
),哪些元素的类型为
int(*)(int,int)
。相反,为每种函数指针类型使用一个单独的数组并避免完全强制转换会更简单。这样做不太容易出错,因为您不会冒险将函数指针作为错误的类型调用(这将是未定义的行为)


更新:
您已经更改了问题,因此
array
现在是
void*
指针的数组。请注意,尽管普通指针可以自由转换为void*,但函数指针却不是这样(尽管在许多实现中它被认为是一个常见的扩展)。

您的数组没有声明为函数指针数组,而是声明为指向void的指针数组

要将数组声明为函数指针数组,可以执行以下操作:

int (*)(int,int) array[5] = ...
或者为了清楚起见:

typedef int (*my_function_pointer_type)(int,int);

my_function_pointer_type array[5] = ... 
理论上,你不能调用一个返回void的函数,并期望它返回一些东西。这是违反C标准的。实际上,如果您这样做,很可能会得到一个不可预测的值,但在某些情况下(例如尝试返回一个结构),使用一些ABI可能会导致崩溃


最好的方法是将“虚拟”函数的类型与放入数组的其他函数的类型相匹配。

谢谢!我刚刚用typedef尝试了你的代码,以使转换更容易阅读,它也可以工作(即typedef int(*ptrInt)(int,int);然后转换就是(ptrInt)数组[1]…)还注意到我必须将数组声明从(*array[5])()=。。。要作废*array[5]=…@jamesdlin为什么不呢?对不起,请忽略我之前的评论。在C99标准的6.3.2.3/8中,将指向函数的指针强制转换为指向函数的不同类型的指针并返回是合法的。@davidefaeli实际上,您现在更新问题的方式使这不完全合法。请参阅对我的答案的更新。注意:标准C不支持将函数指针从
void*
转换到函数指针。编译器可以将其作为扩展提供。在标准C中,您可以强制转换为
void(*)(
),并使用数组类型
void(*array[5])()=…
您可以给出一个如何初始化函数指针数组的示例吗?因为到目前为止我所尝试的都失败了:1)void(*array[2])(void)={ptrAdd,ptrEmpty};2) void(*array[2])(int,int)={ptrAdd,ptrEmpty};3) void(*array[2])(int)={ptrAdd,ptrEmpty};由于指针类型不兼容,编译器不断抛出错误。我不得不求助于一个空指针数组…@davidefaeli你问题的全部要点是你试图将不兼容的函数指针强制到一个数组中。因此,在赋值时需要显式转换到预期的函数指针类型(例如
(void(*)(void))ptrAdd
),并在使用时转换回原始类型。但正如我(和M.M.)已经解释过的,这是为零增益做的大量额外工作。最好声明单独的数组并避免强制转换。