Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Friday, January 1, 2016

void ( *( *f[] ) () ) ()

void ( *( *f[] ) () ) ()


I just saw a picture today and think I'd appreciate explanations. So here is the picture:

some c code

I found this confusing and wondered if such codes are ever practical. I googled the picture and found another picture in this reddit entry, and here is that picture:

some interesting explanation

So this "reading spirally" is something valid? Is this how C compilers parse?
It'd be great if there are simpler explanations for this weird code.
Apart from all, can these kind of codes be useful? If so, where and when?

There is a question about "spiral rule", but I'm not just asking about how it's applied or how expressions are read with that rule. I'm questioning usage of such expressions and spiral rule's validity as well. Regarding these, some nice answers are already posted.

Answer by ouah for void ( *( *f[] ) () ) ()


There is a rule called the "Clockwise/Spiral Rule" to help find the meaning of a complex declaration.

From c-faq:

There are three simple steps to follow:

  1. Starting with the unknown element, move in a spiral/clockwise direction; when ecountering the following elements replace them with the corresponding english statements:

[X] or []

=> Array X size of... or Array undefined size of...

(type1, type2)

=> function passing type1 and type2 returning... * => pointer(s) to...

  1. Keep doing this in a spiral/clockwise direction until all tokens have been covered.

  2. Always resolve anything in parenthesis first!

You can check the link above for examples.

Also note that to help you there is also a website called:

http://www.cdecl.org

You can enter a C declaration and it will give its english meaning. For

void (*(*f[])())()  

it outputs:

declare f as array of pointer to function returning pointer to function returning void

Answer by SergeyA for void ( *( *f[] ) () ) ()


I doubt constructions like this can have any use in real life. I even detest them as interview questions for the regular developers (likely OK for compiler writers). typedefs should be used instead.

Answer by Casey for void ( *( *f[] ) () ) ()


Regarding the usefulness of this, when working with shellcode you see this construct a lot:

int (*ret)() = (int(*)())code;  ret();  

While not quite as syntactically complicated, this particular pattern comes up a lot.

More complete example in this SO question.

So while the usefulness to the extent in the original picture is questionable (I would suggest that any production code should be drastically simplified), there are some syntactical constructs that do come up quite a bit.

Answer by John Bode for void ( *( *f[] ) () ) ()


The "spiral" rule kind of falls out of the following precedence rules:

T *a[]    -- a is an array of pointer to T  T (*a)[]  -- 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  

The subscript [] and function call () operators have higher precedence than unary *, so *f() is parsed as *(f()) and *a[] is parsed as *(a[]).

So if you want a pointer to an array or a pointer to a function, then you need to explicitly group the * with the identifier, as in (*a)[] or (*f)().

Then you realize that a and f can be more complicated expressions than just identifiers; in T (*a)[N], a could be a simple identifier, or it could be a function call like (*f())[N] (a -> f()), or it could be an array like (*p[M])[N], (a -> p[M]), or it could be an array of pointers to functions like (*(*p[M])())[N] (a -> (*p[M])()), etc.

It would be nice if the indirection operator * was postfix instead of unary, which would make declarations somewhat easier to read from left to right (void f[]*()*(); definitely flows better than void (*(*f[])())()), but it's not.

When you come across a hairy declaration like that, start by finding the leftmost identifier and apply the precedence rules above, recursively applying them to any function parameters:

         f              -- f           f[]            -- is an array          *f[]            -- of pointers  ([] has higher precedence than *)         (*f[])()         -- to functions        *(*f[])()         -- returning pointers       (*(*f[])())()      -- to functions  void (*(*f[])())();     -- returning void  

The signal function in the standard library is probably the type specimen for this kind of insanity:

       signal                                       -- signal         signal(                          )           -- is a function with parameters         signal(    sig,                  )           --    sig         signal(int sig,                  )           --    which is an int and         signal(int sig,        func      )           --    func         signal(int sig,       *func      )           --    which is a pointer         signal(int sig,      (*func)(int))           --    to a function taking an int                                                    signal(int sig, void (*func)(int))           --    returning void        *signal(int sig, void (*func)(int))           -- returning a pointer       (*signal(int sig, void (*func)(int)))(int)     -- to a function taking an int  void (*signal(int sig, void (*func)(int)))(int);    -- and returning void  

At this point most people say "use typedefs", which is certainly an option:

typedef void outerfunc(void);  typedef outerfunc *innerfunc(void);    innerfunc *f[N];  

But...

How would you use f in an expression? You know it's an array of pointers, but how do you use it to execute the correct function? You have to go over the typedefs and puzzle out the correct syntax. By contrast, the "naked" version is pretty eyestabby, but it tells you exactly how to use f in an expression (namely, (*(*f[i])())();, assuming neither function takes arguments).

Answer by keshlam for void ( *( *f[] ) () ) ()


Remember these rules for C declares  And precedence never will be in doubt:  Start with the suffix, proceed with the prefix,  And read both sets from the inside, out.  -- me, mid-1980's  

Except as modified by parentheses, of course. And note that the syntax for declaring these exactly mirrors the syntax for using that variable to get an instance of the base class.

Seriously, this isn't hard to learn to do at a glance; you just have to be willing to spend some time practising the skill. If you're going to maintain or adapt C code written by other people, it's definitely worth investing that time. It's also a fun party trick for freaking out other programmers who haven't learned it.

For your own code: as always, the fact that something can be written as a one-liner does't mean it should be, unless it is an extremely common pattern that has become a standard idiom (such as the string-copy loop). You, and those who follow you, will be much happier if you build complex types out of layered typedefs and step-by-step dereferences rather than relying on your ability to generate and parse these "at one swell foop." Performance will be just as good, and code readability and maintainability will be tremendously better.

It could be worse, you know. There was a legal PL/I statement that started with something like:

if if if = then then then = else else else = if then ...  

Answer by Jon Purdy for void ( *( *f[] ) () ) ()


In C, declaration mirrors usage?that?s how it?s defined in the standard. The declaration:

void (*(*f[])())()  

Is an assertion that the expression (*(*f[i])())() produces a result of type void. Which means:

  • f must be an array, since you can index it:

    f[i]  
  • The elements of f must be pointers, since you can dereference them:

    *f[i]  
  • Those pointers must be pointers to functions taking no arguments, since you can call them:

    (*f[i])()  
  • The results of those functions must also be pointers, since you can dereference them:

    *(*f[i])()  
  • Those pointers must also be pointers to functions taking no arguments, since you can call them:

    (*(*f[i])())()  
  • Those function pointers must return void

The ?spiral rule? is just a mnemonic that provides a different way of understanding the same thing.

Answer by Random832 for void ( *( *f[] ) () ) ()


It's only a "spiral" because there happens to be, in this declaration, only one operator on each side within each level of parentheses. Claiming that you proceed "in a spiral" generally would suggest you alternate between arrays and pointers in the declaration int ***foo[][][] when in reality all of the array levels come before any of the pointer levels.


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.