简体   繁体   English

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

[英]Why can `(*)` be omitted from a function pointer inside a function parameter list?

Compiling with gcc8: 用gcc8编译:

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

Gives (only) the following warnings: 给(仅)以下警告:

<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);

Why is the type of f1 the same as f2 ? 为什么f1的类型与f2相同? Only f2 is declared as a function pointer. 只有f2被声明为函数指针。 I would expect f1 not to compile at all, as it names a function type, not a function pointer. 我希望f1根本不会编译,因为它命名一个函数类型,而不是一个函数指针。 What is the rule that says, that a function type inside a function parameter list changes to a pointer to that function type? 什么规则说,函数参数列表中的函数类型更改为指向该函数类型的指针?

Because the standard ( 6.7.6.3p8 ) says that 因为标准( 6.7.6.3p8 )说明了这一点

A declaration of a parameter as ''function returning type'' shall be adjusted to ''pointer to function returning type'', as in 6.3.2.1 . 参数声明为''函数返回类型''应调整为''函数返回类型的指针'',如6.3.2.1所述

It's similar to how arrays parameters are adjusted to pointers (6.7.63.p7) , if you think about it. 它类似于数组参数如何调整为指针(6.7.63.p7) ,如果你考虑它。

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

are compatible declarations, just like: 是兼容的声明,就像:

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

are. 是。


Note that the adjustment doesn't make void some_func(void (*)(void) compatible with void some_other_func(void (**)(void) or void yet_another_func(void (*****)(void) and that as far as functions are concerned, declarations don't really reflect use anymore, (despite that being the intention of the language's original author). In standardized C, due to how function identifiers decay to pointers and due to how it doesn't matter whether you use a function type or a function pointer type to make a call, you can call any function with arbitrarily many * : 请注意,调整不会使void some_func(void (*)(void)void some_other_func(void (**)(void)void yet_another_func(void (*****)(void) void some_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
}

Because in C, in that case, the function name itself is a function pointer. 因为在C中,在这种情况下,函数名本身就是一个函数指针。 See this answer: Why is using the function name as a function pointer equivalent to applying the address-of operator to the function name? 看到这个答案: 为什么使用函数名作为函数指针相当于将address-of运算符应用于函数名?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM