Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing C declarations

Can someone help me figure this declaration out?

int *x()(int)
void (*signal(int, void (*fp)(int)))(int)

I can't seem to parse these using methods given here . I know what this means using cdecl.org and also that the 1st one is illegal but I want to figure out how to parse these?

like image 227
abjoshi - Reinstate Monica Avatar asked Dec 17 '22 21:12

abjoshi - Reinstate Monica


2 Answers

First, some basic rules:

T   *a[N];   // a is an array of pointer to T
T (*a)[N];   // a is a pointer to an array of T
T    *f();   // f is a function returning a pointer to T
T  (*f)();   // f is a pointer to a function returning T
const T *p;  // p is a non-const pointer to const T
T const *p;  // same as above
T * const p; // p is a const pointer to non-const T

In both declarators and expressions, the [] and () operators have higher precedence than the * operator, so you need to explicitly group it with the identifier when working with pointers to arrays ((*a)[N]) and pointers to functions ((*f)()).

When you find a hairy declaration, find the left-most identifier and work your way out, remembering the rules above, and applying them recursively to any function parameters:

       signal                               -- signal
       signal(                    )         -- is a function taking
       signal(                    )         --   parameter unnamed
       signal(int,                )         --     of type int
       signal(int,        fp      )         --   parameter fp
       signal(int,      (*fp)     )         --     is a pointer
       signal(int,      (*fp)(   ))         --     to a function taking
       signal(int,      (*fp)(   ))         --       parameter unnamed
       signal(int,      (*fp)(int))         --       of type int 
       signal(int, void (*fp)(int))         --     returning void
     (*signal(int, void (*fp)(int)))        -- returning a pointer
     (*signal(int, void (*fp)(int)))(   )   --   to a function taking
     (*signal(int, void (*fp)(int)))(   )   --     parameter unnamed
     (*signal(int, void (*fp)(int)))(int)   --     of type int
void (*signal(int, void (*fp)(int)))(int);  --   returning void

In English, signal is a function that takes an integer and a pointer to a signal function as parameters and returns a pointer to a handling function.

Occasionally you don't have an identifier (as in a function prototype where only the types are specified), so you have to mentally put in a placeholder (call it λ) and apply the rules to that placeholder:

void (*signal(int λ, void (*fp)(int λ)))(int λ);

like image 159
John Bode Avatar answered Jan 17 '23 20:01

John Bode


When function returns function pointer, return value surrounds the function name and it's arguments. So it helps to start from the center.

But best way to parse function pointer syntax is not have to parse it at all.

Second example can be written using typedef as:

typedef void funType(int);             // Our function type
funType * signal(int i, funType * fp); // Sane version of the function declaration

When you need to use function pointers, always define the function type first with the typedef.

like image 25
user694733 Avatar answered Jan 17 '23 20:01

user694733