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

时间:2021-08-10 21:16:25

I've seen some examples of array of function-pointers (here, for example)

我已经看到了函数指针数组的一些例子(例如这里)

In the examples I've seen the array holds functions that have a return value of the same type (all int's, or all void's for example).

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

But I'm wondering can you have an array that holds function-pointers of different types?

但是我想知道你能不能有一个包含不同类型的函数指针的数组?

The next code won't compile:

下一个代码不会编译:

#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;
}

It says the problem is with the assignment ret =... "void value not ignored as it ought to be".

它说问题在于任务ret =…“无效价值不应被忽视”。

3 个解决方案

#1


2  

You can do it like this:

你可以这样做:

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

You need to cast to pointer to function type with the correct signature.

您需要使用正确的签名将指针转换为函数类型。

#2


2  

But I'm wondering can you have an array that holds function-pointers of different types?

但是我想知道你能不能有一个包含不同类型的函数指针的数组?

As noted in Anatoly's answer, your code doesn't work because your array intends to declare contain pointers-to-functions that return void, but then you try invoking it as a pointer-to-function that returns int. These are incompatible types, so an explicit cast is required. And, as noted in section 6.3.2.3/8 of the ISO C99 standard, casting a function pointer to a different function pointer type and back again is permitted:

正如Anatoly的回答所指出的,您的代码不能工作,因为您的数组打算声明包含返回void的从指针到函数的函数,但是您尝试将它作为返回int的指针到函数来调用。并且,如ISO C99标准第6.3.2.3/8节所述,允许将函数指针转换为不同的函数指针类型,然后再返回:

A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.

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

That said, I don't see any point to doing this. The function pointer cast is a static cast (a cast known to the compiler) and not a dynamic cast, so you must manually keep track of which elements in your array are of type void (*)() and which are of type int (*)(int, int). It'd instead be simpler to have a separate array for each function pointer type and avoid casting altogether. Doing so would be less error-prone since you would not risk invoking a function pointer as the wrong type (which would be undefined behavior).

也就是说,我认为这样做没有意义。函数指针强制转换是静态强制转换(编译器知道的强制转换),而不是动态强制转换,因此您必须手动跟踪数组中的哪些元素是void (*)() () () () ())(*)(int (int, int))类型。相反,为每个函数指针类型设置一个单独的数组并避免强制转换会更简单。这样做会减少出错的可能性,因为您不会将调用函数指针作为错误类型(这将是未定义的行为)。


Update: You've changed your question so that array is now an array of void* pointers. Note that although normal pointers may be freely cast to and from void*, this is not true for function pointers (although it is considered to be a common extension in many implementations).

更新:您已经更改了您的问题,所以该数组现在是一个void*指针数组。注意,虽然普通指针可以*转换为或从void*中转换,但这对于函数指针是不正确的(尽管在许多实现中它被认为是一个常见的扩展)。

#3


0  

Your array is not declared as an array of function pointers, it is declared as an array of pointers to void.

数组不是作为函数指针的数组声明的,而是作为指向void的指针数组声明的。

To declare the array as an array of function pointers you can do:

要将数组声明为函数指针的数组,您可以这样做:

int (*)(int,int) array[5] = ...

or for clarity:

或为了清晰:

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

my_function_pointer_type array[5] = ... 

In theory, you cannot call a function which returns void and expect it to return something. This is against the C standard. In practice, if you do this you most likely get an unpredictable value, but in some cases (such as trying to return a structure) with some ABIs you can get a crash.

在理论上,不能调用返回void的函数并期望它返回某些东西。这是违反C标准的。在实践中,如果您这样做,您很可能会得到一个不可预测的值,但是在某些情况下(例如尝试返回一个结构),您可能会得到一个ABIs崩溃。

The best way is to match the type of your "dummy" function to the type of other functions being put into the array.

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

#1


2  

You can do it like this:

你可以这样做:

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

You need to cast to pointer to function type with the correct signature.

您需要使用正确的签名将指针转换为函数类型。

#2


2  

But I'm wondering can you have an array that holds function-pointers of different types?

但是我想知道你能不能有一个包含不同类型的函数指针的数组?

As noted in Anatoly's answer, your code doesn't work because your array intends to declare contain pointers-to-functions that return void, but then you try invoking it as a pointer-to-function that returns int. These are incompatible types, so an explicit cast is required. And, as noted in section 6.3.2.3/8 of the ISO C99 standard, casting a function pointer to a different function pointer type and back again is permitted:

正如Anatoly的回答所指出的,您的代码不能工作,因为您的数组打算声明包含返回void的从指针到函数的函数,但是您尝试将它作为返回int的指针到函数来调用。并且,如ISO C99标准第6.3.2.3/8节所述,允许将函数指针转换为不同的函数指针类型,然后再返回:

A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.

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

That said, I don't see any point to doing this. The function pointer cast is a static cast (a cast known to the compiler) and not a dynamic cast, so you must manually keep track of which elements in your array are of type void (*)() and which are of type int (*)(int, int). It'd instead be simpler to have a separate array for each function pointer type and avoid casting altogether. Doing so would be less error-prone since you would not risk invoking a function pointer as the wrong type (which would be undefined behavior).

也就是说,我认为这样做没有意义。函数指针强制转换是静态强制转换(编译器知道的强制转换),而不是动态强制转换,因此您必须手动跟踪数组中的哪些元素是void (*)() () () () ())(*)(int (int, int))类型。相反,为每个函数指针类型设置一个单独的数组并避免强制转换会更简单。这样做会减少出错的可能性,因为您不会将调用函数指针作为错误类型(这将是未定义的行为)。


Update: You've changed your question so that array is now an array of void* pointers. Note that although normal pointers may be freely cast to and from void*, this is not true for function pointers (although it is considered to be a common extension in many implementations).

更新:您已经更改了您的问题,所以该数组现在是一个void*指针数组。注意,虽然普通指针可以*转换为或从void*中转换,但这对于函数指针是不正确的(尽管在许多实现中它被认为是一个常见的扩展)。

#3


0  

Your array is not declared as an array of function pointers, it is declared as an array of pointers to void.

数组不是作为函数指针的数组声明的,而是作为指向void的指针数组声明的。

To declare the array as an array of function pointers you can do:

要将数组声明为函数指针的数组,您可以这样做:

int (*)(int,int) array[5] = ...

or for clarity:

或为了清晰:

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

my_function_pointer_type array[5] = ... 

In theory, you cannot call a function which returns void and expect it to return something. This is against the C standard. In practice, if you do this you most likely get an unpredictable value, but in some cases (such as trying to return a structure) with some ABIs you can get a crash.

在理论上,不能调用返回void的函数并期望它返回某些东西。这是违反C标准的。在实践中,如果您这样做,您很可能会得到一个不可预测的值,但是在某些情况下(例如尝试返回一个结构),您可能会得到一个ABIs崩溃。

The best way is to match the type of your "dummy" function to the type of other functions being put into the array.

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