为什么可以在函数参数列表内的函数指针中省略`(*)?

时间:2018-10-25 19:22:22

标签: c

使用gcc8进行编译:

#include <stdio.h>
void some_func(void f1(void), void (*f2)(void))
{
    printf("%d\n", f1);
    printf("%d\n", f2);
}

(仅)给出以下警告:

<source>:11:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'void (*)(void)' [-Wformat=]
     printf("%d\n", f1);
<source>:12:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'void (*)(void)' [-Wformat=]
     printf("%d\n", f2);

为什么f1的类型与f2相同?仅将f2声明为函数指针。我希望f1根本不会编译,因为它命名为函数类型,而不是函数指针。什么规则说,函数参数列表中的函数类型更改为指向该函数类型的指针?

2 个答案:

答案 0 :(得分:20)

因为标准(6.7.6.3p8)表示

  

将参数声明为“函数返回类型”应为   调整为“指向函数返回类型的指针”,如6.3.2.1

如果您考虑的话,它类似于arrays parameters are adjusted to pointers (6.7.63.p7) 的方式。

void some_func(void (void));
void some_func(void (*)(void));

是兼容的声明,就像:

void other_func(char string[]);
void other_func(char *string);

是。


请注意,该调整不使void some_func(void (*)(void)void some_other_func(void (**)(void)void yet_another_func(void (*****)(void)兼容,并且就功能而言,声明不再真正反映使用,(尽管是该语言的原始作者的意图)。在标准化C语言中,由于函数标识符如何衰减为指针,以及由于使用函数类型还是函数指针类型进行调用都无关紧要,因此可以使用任意多个*来调用任何函数:

#include <stdio.h>
int main()
{
    (*puts)("hello world");
    (******puts)("hello world");
    (***&*&*puts)("hello world"); //& cancels a * as per 6.5.3.2p3

    int (*p)(char const*) = puts;
    int (**pp)(char const*) = &p;
    int (***ppp)(char const*) = &pp;

    (**ppp)("hello world"); //at least two asterisks required here
}

答案 1 :(得分:0)