1. 12

  2. 5

    Who invents a language that needs such a complicated rule to read variable declarations? (This is a rhetorical question. We all know who invented C.) The fact that it’s consistent and logical doesn’t make it simple. Human language doesn’t generally read clockwise. Left-to-right or right-to-left, sure, but not clockwise.

    1. 3

      As you say, this is a general rule with some exceptions. :)

      1. 2

        On a related note…not left-to-right or right-to-left, but left-to-right and right-to-left.

      2. 3

        I think I remember hearing somewhere that K&R later came to the conclusion that making the unary (*) operator go on the left instead of on the right was a mistake, but one whose consequences didn’t really become clear until after the grammar was already effectively fixed. I’m not confident in the veracity of that.

        I can’t personally imagine the machines on which early C programs ran being able to fit enough code to make pointers to functions that take and return other pointers to functions be something that one would see very often?

        1. 1

          The fact that it’s consistent and logical doesn’t make it simple

          Agreed. I think “C pointers” is such a complex subject for so many people (how many other languages have books written just about their pointer handling alone - I can’t think of another), but the majority of that is caused by the syntax rather than the concepts themselves. I used and understood pointers just fine in other languages (including x86 assembly language) but the syntax tripped me up for a long time when I started programming in C - the simple cases are fine, it’s the more complex nested cases that did me in.

        2. 4

          If a declaration is complicated enough that you don’t want to parse it in your head, you can just use the command-line tool cdecl or its online version http://cdecl.org/. It converts “C gibberish ↔ English”. (That’s right, it converts both ways.)

          For instance, example #2 in the article is char *(*fp)( int, float *);. After reading in spiral order, the article shows that you can understand the declaration as “fp is a pointer to a function passing an int and a pointer to float returning a pointer to a char”. But if you just paste that declaration into cdecl, it tells you the same thing: that line will “declare fp as pointer to function (int, pointer to float) returning pointer to char”.

          1. 2

            I’ve always preferred the right-left rule.