C : 为什么可以将 void 函数强制转换为 "pointer to function returning pointer to pointer to void"

C : why is that cast of void function to "pointer to function returning pointer to pointer to void" possible

#include <stdio.h>

void hello() {
    printf("hello world\n");
}

int main() {
    void *(*gibberish)() = (void *(*)())hello;
    (*gibberish)();
    void (*simple)() = &hello;
    (*simple)();
    return 0;
}
$ cc pt_func.c && ./a.out
hello world
hello world

嗨,C 中的函数指针让我很困惑。第二个定义(简单)非常清楚:我们获取 hello 的地址,并将其放入我们可以使用的函数指针中。

然而,第一个对我来说有点陌生。为什么它有效?如何将指向 void 的 void 函数强制转换为指向返回指向 void 的指针的函数的指针?

编译器如何处理这样的转换?

首先,当函数指示符(包括函数名称,例如 hello)用于表达式而不是 sizeof 或一元 & 的操作数时,根据 C 2018 6.3.2.1 4,它会自动转换为指向函数的指针。因此,在 void (*simple)() = &hello; 中,不需要 &void (*simple)() = hello; 会自动使用函数的地址。这解释了为什么 void *(*gibberish)() = (void *(*)())hello;.

中不需要 &

其次,强制转换是因为C 6.3.2.3 8 says

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…

但是,此转换旨在允许将函数指针临时转换为通用类型,以便存储。检索指针时,应在使用它调用函数之前将其转换回适当的类型。第 8 段继续:

… If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.