简体   繁体   中英

About a declaration of function pointer

I'm thinking about the difference between:

void *signal(int, void (*)(int))(int)

and

void (*signal(int, void (*)(int)))(int)

I know the latter is from here - Example #3: The ``Ultimate'' (it's a hilarious learning experience when I was trying speak out loud to understand it):

signal is a function takes (int, void (*)(int)) as input and returns a pointer to another function that takes (int) and returns void .

For the former I'm thinking that since the last (int) will have higher precedence than * so it should be a syntax error, but from cdecl.org the result is:

["] declare signal as function (int, pointer to function (int) returning void) returning function (int) returning pointer to void [."]

So I need a check.

One has to differentiate between grammar and semantics. cdecl.org only gives you the grammatical meaning of whatever declarator you type into it. In your first example, you have indeed a grammatically correct declaration of signal as a function returning a function. However, C does not allow functions to return other functions:

N1570 6.7.6.3 §1:

A function declarator shall not specify a return type that is a function type or an array type.

So while this declaration is grammatically correct, it is semantically invalid. In other words: While the C syntax makes it possible to write "function returning a function", you're not allowed to actually have a function that returns a function in a program. Just like the English language (or any language for that matter) also allows you to express all sorts of thoughts that would physically be impossible to carry out…

The most important part here is... you don't need to learn this, it is a very poorly designed part of the language. You can scroll down to the bottom of the answer to find the sane, professional solution.

Otherwise, if you insist, it goes like this...


When trying to return a function pointer from a function, the type of the function pointer gets split up. If you want to return a function pointer void(*)(void) , then this poor function pointer gets split up in 3 parts. Lets call them like this:

  • void is A, the return type of the pointed-at function.
  • (*) is B, marking this a pointer to function, rather than a function.
  • (void) is C, the parameters of the pointed-at function.

Then if we want to stick this as a return type into some other icky function declaration, they end up like this:

#define A void
#define B *
#define C (void)

// A (B) C equals void(*)(void)

A (B madness(int, void (*fp)(int))) C;

where A, B and C are the parts of our poor function pointer to be returned, madness is the name of the function, and the rest is some mess used as parameters by the function itself.

If we omit the B part, it will be interpreted like a function returning another function of type void f (void); which isn't valid. The syntax allows it but not the language specification.

Similarly, int foo (void) [3]; - a function returning an array, is not allowed either.


Pondering these things is the road to madness and it makes the code unreadable. Professional programmers use typedef .

Given

void (*madness(int, void (*f)(int)))(int);

replace it with:

typedef void func_t (int);

func_t* sanity (int, func_t* f);

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