转换 A 函数指针 Return 输入 C

Casting A Function Pointers Return Type in C

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

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

//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. 这与我每次调用函数时仅对 return 值进行类型转换有何不同,如下所示?

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

  2. 如果不一样,能行吗?看了this discussion, and this one,似乎归结为兼容性问题。由于原始函数是 returning void* ,如果我没记错的话它应该是兼容的。

根据标准C,这都是未定义的行为。被调用的函数指针的类型必须匹配函数的定义类型(除了()可以匹配任何参数列表)。

标准中"compatible"这个词的意思非常严格,基本上就是"the same"。尽管 void * 可以隐式转换为 int *,但它们不是 兼容类型

对于要定义行为的代码,您可以执行第 1 点中的建议。您可以将其包装在宏或包装函数中。

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 Brahmakshatriya points out in a ,一些 ABI(应用程序二进制接口)可以对不同的函数类型有不同的调用约定,因此将函数指针转换为 'wrong' 类型,然后通过该转换后的指针调用它可能会结束也造成破坏。这尤其适用于指针、浮点数和其他类型。通常(但绝不保证),函数 returning 指针将 return 指针以相同的方式而不考虑指针的类型 returned.

并且§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)来获得所需的效果,然后内联函数可能会有用。