Live data from Hacker News

The Clockwise/Spiral Rule of C declarations

c-faq.com

71–72 of 72 posts

Re: The Clockwise/Spiral Rule of C declarations

#71
post #12

Things break down utterly in the presence of typedefs. What is this? foo(*baz(bing,boff(*bratz)(biff)))(buff);

The “spiral rule” is just an approximation of the actual rule as defined in the standard: declaration follows usage. Even with typedefs, that declaration means “when you call baz with a bing and a pointer (named bratz) to a function of type boff(biff), then you get back a pointer to a function of type foo(buff).” It’s an extremely concise notation for expressing type information without (much) special type syntax, an…

I'm impressed. How did you know where to start?

Re: The Clockwise/Spiral Rule of C declarations

#72
post #71

Earlier quoted context omitted.

The “spiral rule” is just an approximation of the actual rule as defined in the standard: declaration follows usage. Even with typedefs, that declaration means “when you call baz with a bing and a pointer (named bratz) to a function of type boff(biff), then you get back a pointer to a function of type foo(buff).” It’s an extremely concise notation for expressing type information without (much) special type syntax, an…

I'm impressed. How did you know where to start?

In C, the statement “type declarator;” is an assertion that “declarator” has the type “type”. In other words, if you read “declarator” as an expression (more or less), then it should have the type “type”. So here:

    foo (*baz(bing, boff (*bratz)(biff)))(buff);
“foo” is the type, and the rest is the declarator. Then you just break it down according to the usual precedence rules:

    baz(…)
“baz” is a function…

    baz(bing, …)
…which takes a “bing”, and…

    *bratz
…a pointer (arbitrarily named “bratz”)…

    (*bratz)(biff)
…to a function which takes a “biff”…

    boff(*bratz)(biff)
…and returns a “boff”…

    *baz(…)
…and “baz” returns a pointer…

    (*baz(…))(buff)
…to a function taking a “buff”…

    foo (*baz(…))(buff)
…and returning a “foo”.

With typedefs for function pointer types:

    typedef boff (*bratz_t)(biff);
    typedef foo (*baz_ret_t)(buff);

    baz_ret_t baz(bing, bratz_t);
Or for function types:

    typedef boff bratz_t(biff);
    typedef foo baz_ret_t(buff);

    baz_ret_t *baz(bing, bratz_t *);
Post reply on HN