Live data from Hacker News

The "Clockwise/Spiral Rule" in C

c-faq.com

1–10 of 49 posts

Re: The "Clockwise/Spiral Rule" in C

#2
This is great. Functions like signal are rare, so I just memorize what they do without reading the decl every time. Also, typedefs for function pointers go a LONG way towards readability.

The point at the end about const is good too. I see a lot of people screwing that up and consting the wrong piece.

Re: The "Clockwise/Spiral Rule" in C

#6
In practice, nobody uses a "clockwise/spiral rule" to read C declarations; they typedef complex declarations into bite-sized components.

C declarations are hardest to understand when they involve (1) "arrays"† of "arrays" of "arrays", (2) function pointers, and (3) multiple layers of indirection.

In systems and networking code and in most application code, (1) "multi-level arrays" are uncommon, and they're uncommon in roughly the same way tuples of tuples of tuples are uncommon in Python: they're a symptom that you're missing a level of abstraction.

Function pointer declarations (2) are common and annoying to read. However, in virtually all cases, the core of what you're trying to express with a function pointer declaration is "what arguments does this function take" and "what does it return". More importantly, most idiomatic C code typedefs function pointers, so you're not looking at prototype decls with nested complex function pointer decls inside of them.

So instead of

    void (*signal(int sig, void (*func)(int)))(int);
a modern C programmer would expect

     typedef void (*sig_t) (int);

     sig_t signal(int sig, sig_t func);
The qsort(3) man page is another example of an archaic declaration (its authors presumably think this is the clearest way to convey qsort to an experienced programmer); check out the man page for pcap_loop(3) for a better example.

In most C code, multiple layers of indirection (3) are one-step pointers-to-pointers used to work around call-by-value in C. If you store in your head the notion that a pointer to a pointer is just there to provide a return-value argument, that's probably all you'd need to remember about it. Pointers to pointers to pointers are rare.

C pedants: I'm using "array" in an intentionally vague sense.

Re: The "Clockwise/Spiral Rule" in C

#7
post #3

http://cdecl.org/

Cool, but it doesn't handle the last example: void (*signal(int, void (*fp)(int)))(int) ...claims there's a syntax error, and there might be, but I don't know off-hand.

It's confused by the parameter name fp.

    cdecl> explain void (*signal(int, void (*)(int)))(int) ;

    declare signal as function (int, pointer to function (int) returning void) returning pointer to function (int) returning void

Re: The "Clockwise/Spiral Rule" in C

#8
post #3

http://cdecl.org/

Cool, but it doesn't handle the last example: void (*signal(int, void (*fp)(int)))(int) ...claims there's a syntax error, and there might be, but I don't know off-hand.

This works:

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

Re: The "Clockwise/Spiral Rule" in C

#9
The "spiral rule" makes for pretty pictures, but unfortunately it isn't correct. One simple example:

    int *foo[3][4];
The spiral rule would have us read this as "foo is an array [3] of pointers to array [4] of int". What it actually is is "foo is an array [3] of arrays [4] of pointers to int".

The correct rule* for parsing declarations is "Start from the thing being declared, and read right until you hit a closing parenthesis, then read left until you reach the matching paren, then go back to reading right, and always skip over any tokens you've already read." This is sometimes called the "right-left rule"; it's not as pretty as "spiral", but it actually works.

(*) the really correct rule is "follow the syntax and semantics specified in the language standard", but for some reason that confuses people.

Re: The "Clockwise/Spiral Rule" in C

#10
post #4

This is why most programmers are more productive with newer languages. Syntax and readability matter.

"Readability" has virtually nothing to do with why people are more productive in higher level languages. Pointer declarations address a problem most high level languages don't even allow developers to engage.
Post reply on HN