在 C 中转换函数指针返回类型

标签 c casting function-pointers

我有一个返回 void 指针 (void*) 的后端函数,并且有几个指向它的前端函数指针。然而,每个前端函数指针都需要返回不同的类型(但始终是指针)。因为每个前端函数指针总是具有相同的唯一返回类型,所以我认为可以将每个前端指针的返回类型类型转换为其各自的返回类型。

希望我下面的代码能够比我更好地解释:

//Backend function definition
void* addElement(void *memBlock, size_t origSize, size_t additionalSize){
    return realloc(memBlock, origSize+additionalSize);
}

//Front end function pointers
int*(*addInt)(void*, size_t, size_t)=addElement;
char*(*addChar)(void, size_t, size_t) addChar=addElement;

我的问题有两个:

  1. 这与每次调用函数时仅对返回值进行类型转换(如下所示)有何不同?

    int *var=(int *)addElement(...);

  2. 如果不同,它会起作用吗?已阅读this discussion ,和this one ,这似乎归结为兼容性问题。由于原始函数返回 void*,如果我没有记错的话,它应该是兼容的。

最佳答案

C11标准§6.2.5 Types ¶28说:

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.48) Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements.

这特别意味着指向函数的指针不必具有与任何指向对象类型的指针相同的表示形式。存在,或者至少曾经存在,指向函数的指针比指向对象的指针更大的机器(我指的不是小型、中型、紧凑型、大型、巨型模型和 80x86 芯片——我相信 IBM AS/400,后来的 iSeries ,具有比任何指向对象的指针都大的函数指针)。另外,如Ajay Brahmakshatriyacomment 中指出,一些 ABI(应用程序二进制接口(interface))对于不同的函数类型可能有不同的调用约定,因此将函数指针转换为“错误”类型,然后通过转换后的指针调用它也可能最终造成严重破坏。这尤其适用于指针、浮点和其他类型。通常(但绝不保证),返回指针的函数将以相同的方式返回指针,无论返回的指针是什么类型。

§6.3.2.3 Pointers ¶7-8说:

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned68) for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

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 referenced type, the behavior is undefined.

在编写代码时,您将通过强制转换类型调用该函数,这将导致未定义的行为。它可能有效,但可能会停止工作,并且除了重写代码以避免未定义的行为之外,您别无选择。

这意味着您不应该编写问题中所示的前端函数指针。不过,您可以使用简单的封面函数来完成您想要的工作:

static int *addIntFunc(void *mem, size_t old_size, size_t extra_size)
{
    return addElement(mem, old_size, extra_size);
}

int *(*addInt)(void *, size_t, size_t) = addIntFunc;

您可能无法有效地内联该函数;函数指针必须指向一个函数。

或者,实际上,您可以简单地使用 addIntFunc(可能重命名为 addInt)来获得所需的效果,然后内联函数可能会很有用。

关于在 C 中转换函数指针返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50850108/

相关文章:

c - 如何针对大输入调试此 C 程序?

c - 仅基于 printf 语句的程序段错误

c# - C# 中是否可以将服务结果自动转换为相同类型?

c - 在 C 中初始化函数指针

c - 2d-array- arr[][0] 是什么意思?

选择多平台数据可视化的编程语言

sockets - 如何在 swift 中将 sockaddr 转换为 sockaddr_in

c# - 无法将 0 或 1 转换为 C# 中的 boolean 值

c++ - 将任何类的任何成员函数作为回调函数传递

glsl 函数指针(或等效的)