简体   繁体   中英

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

Compiling with 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 ? Only f2 is declared as a function pointer. I would expect f1 not to compile at all, as it names a function type, not a function pointer. 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

A declaration of a parameter as ''function returning type'' shall be adjusted to ''pointer to function returning type'', as in 6.3.2.1 .

It's similar to how arrays parameters are adjusted to pointers (6.7.63.p7) , if you think about it.

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 * :

#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. See this answer: Why is using the function name as a function pointer equivalent to applying the address-of operator to the function name?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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