通过将函数指针强制转换为一个 void 函数然后调用它,"trash" 一个 return 值是未定义的行为吗?

Is it undefined behavior to "trash" a return value by casting the function pointer to a void function then calling it?

比如说,像这样:

int SayHelloThenReturnTen(void) {
    puts("Hello world");
    return 10;
}

然后:

((void(*)(void))SayHelloThenReturnTen)();

这样安全吗?通过转换为 void 指针 "trash" 值 return 是否安全?这是安全和跨平台的,还是 未定义的行为?

这是未定义的行为,因为您正在通过不兼容的函数指针类型调用函数。

如果您不想使用 return 值,请不要使用它:

SayHelloThenReturnTen();

或将结果表达式转换为 void:

(void)SayHelloThenReturnTen();

Is that safe?

将函数指针转换为任何函数指针类型都是安全的。将结果转换回原始类型将产生一个等于原始指针的指针值。

安全,但是,调用一个函数通过一个类型与它所指向的函数不兼容的函数指针点。这在标准的第 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 referenced type, the behavior is undefined.

(强调)

Is it safe to "trash" the return value by casting to a void pointer?

你的例子没有证明这一点。相反,它演示了转换为具有 void return 类型的函数指针类型。同样,演员表还可以,但电话不是。

Is this safe and cross platform, or is this undefined behavior?

它不安全并且有未定义的行为。而且,绝对得不到任何好处。如果愿意,您可以简单地忽略函数的 return 值。如果您试图消除编译器关于这样做的警告,那么,

  1. 考虑一下编译器可能有一点,并且
  2. 如果您想向编译器传达您确实想要忽略 return 值,那么将 转换为更清晰、更简单、更安全 无效:

    (void) SayHelloThenReturnTen();
    

一些实现通过指定获取函数的地址将产生一个指向机器代码函数的指针来扩展语言,该函数以执行记录的方式检索参数和return它的值(如果有的话)环境,而不考虑它实际上是如何被调用的,并且通过函数指针进行的调用将始终以执行环境记录的方式进行处理,而不考虑指针针对的是哪种函数。如果按照描述处理特定函数调用会导致特定行为,那么这样的实现会将其定义为该调用的行为,而不考虑标准是否要求它这样做。在许多这样的实现中,可以将像 int dummy(void) { return 0;} 这样的函数的地址转换为 returns intvoid 的任何函数类型,而不必编写单独的虚拟对象每个签名的功能。

然而,是否有任何特定实现以这种方式处理事物的问题不在标准的管辖范围内。在禁用优化的情况下调用时,通用平台的大多数实现都会以这种方式运行,但启用优化的效果可能无法预测。