Live data from Hacker News

The Clockwise/Spiral Rule of C declarations

c-faq.com

21–30 of 72 posts

Re: The Clockwise/Spiral Rule of C declarations

#21
post #14
post #7

Earlier quoted context omitted.

For this reason I strongly prefer writing char const rather than const char Is there a reason to prefer the second version? It's a lot more popular in my experience.

It's the difference between "declare a constant integer" and "declare an integer constant" and to me the former more accurately represents what you're doing since `const` is modifying `int`, `int` isn't modifying `const`.

Putting const on the right makes more sense when you have pointers or references. Then you just always read from right to left: `int const ` is a pointer to constant integer whereas `int const` is a constant pointer to integer.

Also your argument about which modifies which is strongly anglocentric: there are plenty of people whose native language puts modifiers after the things they modify.

Re: The Clockwise/Spiral Rule of C declarations

#22

Way simpler: from inside out, read any subpart of the type as an expression. (Arrays have precedence over pointers, as usual.) The type that remains is that expression's type. So e.g. given the type: const char *foo[][50] the following expressions have the following types: foo -> const char *[][50] foo[0] -> const char * [50] foo[0][0] -> const char * *foo[0][0] -> const char Another example: int (*const bar)[restric…

What happened to the const in the second example?

Yeah, I think they confused

  const *
with

  * const

Re: The Clockwise/Spiral Rule of C declarations

#23
post #15

Just don't make complex declarations in C, it's almost never useful and won't help anyone out. It'll confuse people and make your code write-only. Just put in a couple extra lines of code somewhere if you have to. It won't be the end of the world.

It'll certainly confuse people, but only those who aren't qualified to be doing anything with the code anyway.

"complex" is subjective. It reminds me of stupid "rules" like "don't use the ternary operator", "every function must be less than 20 lines" (I am not exaggerating --- this was on a Java project, however); and you could easily extend that to "every statement must have a maximum of one operator", "you must not use parentheses", "you must not use more than one level of indirection", etc. Where do you stop? To borrow a saying from UI, "if you write code that even an idiot can understand, only idiots will want to work on it." I don't think we should be forcing programmers to dumb-down code at all.

That said, I'm not advocating for overly complex solutions, and will definitely prefer a simpler solution, but you should know and use the language fully to your benefit.

Re: The Clockwise/Spiral Rule of C declarations

#24

Contrast the first example with Golang: str [10]*byte which reads exactly as it is declared: "str is an array of length 10 of pointers to byte" (byte is Go equivalent of C char (mostly)).

I am not familiar with Go, and have heard many praises of its declaration syntax, but is its dereference operator postfix? That would make sense in such a case. On the other hand, IMHO the whole "make declarations read left-to-right" idea is misguided --- plenty of other constructs exist in programming languages which simply can't be read left-to-right, but are nested according to precedence. I mean, you might as wel…

Go's defererence operator `*` is prefix, like in C.

The point here is that type declarations are regular to read, and those tend to be the tricky ones. Expressions tend not to be so difficult, and are more commonly factored if they become complex. For various reason, type declarations are not so practically factorable.

Re: The Clockwise/Spiral Rule of C declarations

#25
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, and I think it’s quite elegant in that way.

Re: The Clockwise/Spiral Rule of C declarations

#26
post #20

Contrast the first example with Golang: str [10]*byte which reads exactly as it is declared: "str is an array of length 10 of pointers to byte" (byte is Go equivalent of C char (mostly)).

It can also be simpler if you use idiomatic modern C++ with std::array and std::function .

Or Nim:

    var str: array[10, ptr byte]
(and much richer types)

Edit: and while I'm here, Nim has other sensible syntax for this low level stuff...

    var b: byte = 10
    str[0] = addr b
    echo $str[0][]

Re: The Clockwise/Spiral Rule of C declarations

#29
post #20

Contrast the first example with Golang: str [10]*byte which reads exactly as it is declared: "str is an array of length 10 of pointers to byte" (byte is Go equivalent of C char (mostly)).

It can also be simpler if you use idiomatic modern C++ with std::array and std::function .

Looking at "idiomatic modern C++", I am often at a loss for words at what lengths they've gone to in order to reinvent things while greatly obfuscating them in the process. Is there a std::pointer_to too? I don't know, but something like this

    std::array, 10> str;
certainly does not look any more readable to me than

    byte *str[10];
. (Disclaimer: I mainly work with C, but find some C++ features genuinely useful, although the majority of the time they seem more like absurd complexity for the sake of complexity.)

Re: The Clockwise/Spiral Rule of C declarations

#30

While cdecl was probably written before some of you where born it still does precisely one thing and does it well. Cdecl (and c++decl) is a program for encoding and decoding C (or C++) type declarations. http://linuxcommand.org/man_pages/cdecl1.html

Notably, one of the exercises in K&R (with a solution provided) is to write a mostly complete version of cdecl, which I think is great for dispelling much of the "magic" and increasing the understanding of how declarations are actually parsed.
Post reply on HN