将函数转换为 void 返回类型后调用该函数是否安全?

Sza*_*lcs 3 c standards casting calling-convention

我有一个返回值的函数。将其转换为不返回任何内容 ( void) 的函数指针类型然后调用它是否安全?C 标准是否提供了足够的保证,使其在任何平台上都是安全的,并且相当于正常调用该函数而忽略返回值?

额外问题:是否存在在某些平台上实际使用的符合标准的调用约定,但这样做并不安全?


示例代码:

#include <stdio.h>

// simple function with a a side-effect;
// it is useful to call even when ignoring the return value
int f(int x) {
    return printf("%d\n", x);
}

typedef void (*fun_t)(int);

int main() {
    fun_t g = &f; // cast to void return type, issues a warning
    g(123);       // <-- is this safe, and equivalent to calling f(123) instead?
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 这个问题只涉及在转换过程中更改返回类型,而不是更改任何函数参数的类型。
  • 我知道这在我使用的 x86 和 x64 平台上是安全的(假设默认调用约定),但我想知道它通常是否安全。
  • 我知道在必要时通过编写包装器可以很容易地解决这个问题void fw(int x) { f(x); }。但是,我仍然想知道这样做是否安全,以便我可以更好地理解 C 语言的基础知识。

tst*_*isl 7

否。此调用会调用Undefined Behaviour。请参阅https://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p8

指向一种类型函数的指针可以转换为指向另一种类型函数的指针,然后再转换回来;结果应等于原始指针。如果转换后的指针用于调用其类型与引用类型不兼容的函数,则行为为 undefined

在链接https://port70.net/~nsz/c/c11/n1570.html#6.7.6.3p15可以找到函数类型兼容性规则:

为了使两个函数类型兼容,两者都应指定兼容的返回类型。此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用方面一致;相应的参数应具有兼容的类型。...