C语言 为什么'int(*)(float)'指向'int foo()`时会触发警告,而' int(*)(double)'指向它时不会?

e5njpo68  于 2023-01-25  发布在  其他
关注(0)|答案(1)|浏览(161)

我有这样一段代码:

int foo() { return 0; }
int main()
{
    int (*float_function)(float) = foo;
}

使用x86-64 GCC 12.2编译时,如果使用-Wall,则会生成警告(Link):
警告:从不兼容的指针类型“int()()”初始化“int()(float)"[-Wincompatible-pointer-types]
但是,当我从float更改为doubleLink)时:

int foo(){ return 0;}
int main()
{
    int (*double_function)(double) = foo;
}

警告现在消失了。
但我认为这两个都应该得到警告。
我哪里错了吗?为什么GCC不抱怨第二个例子?

irlmq6kh

irlmq6kh1#

声明int foo()时未指定其参数。这是一个过时的功能,允许您使用任何参数调用它。调用函数时,整数参数将提升为int(如果需要),float参数将提升为double
因此,该函数不可能接收float参数,这使得它与int (*)(float)不兼容,但与int (*)(double)不兼容。
如果你想要一个不带参数的函数,那么就声明为int foo(void),这会使它与两者都不兼容。
注意,即使使用double,代码也不是有效的C代码,因为int foo() {...}是一个函数定义,所以编译器知道它没有参数(参见chux的注解,下面是标准参考)。
如果用声明int foo();代替,并将定义放在其他地方,则上述内容是正确的。在这种情况下,相关的标准引用(C17 6.7.6.3/15)为:
为了使两个函数类型兼容,[...]如果一个类型具有参数类型列表,而另一个类型由不属于函数定义的函数声明符指定,并且包含空标识符列表,[...]则每个参数的类型都应与应用默认参数提升所产生的类型兼容。

相关问题