C style peeve and knowing the rules

Christopher North-Keys erlkonig at walt.cc.utexas.edu
Thu Mar 29 21:58:11 AEST 1990


I found this "gem" on the net somewhere.  This strikes me as a good
example not to follow, at least in term of commenting.  Parenthesization
would have helped, but then again, we probably still would have wasted
hours figuring out the *meaning* behind the bloody thing, and probably still
wouldn't understand the main line inside the loop.

Now, there are two ways of looking at this code.  The first is the inevitable
recollection that C actually has contests congratulating the least-readable
code.  The second is more subtle:  I have yet to find (even in C) a decent
way to express the fuctionality of the for() statement in this program, yet
due to the language's flexibility the programmer managed it.  His *comments*
are miserable (nay, sir; they were absent), but the flexibility of a language
evidenced by the creation of a new loop idiom is *very* impressive.

...No, I don't code this way either, that's not the point.

As to those advocating minimalistic parenthesization, there is always the
chance that one's program will be compiled on an errant compiler.  The bug
could take a *long* time to find.  There are also instances in preprocessor
macro definitions where lenient parenthesis will mangle code, and let's not
forget the possibility of making a mistake -- there are over 15 levels of
operator precedence in the K&R C guide.

Of course there are those who will *insist* that math expressions, like
program sources, are fully self documenting.  Example: "Hey, you know that
you don't need to comment code, don't you?  You really *use* comments?
But the good programmers don't *need* them, they just clutter up the code...
What kind of programmer *are* you anyway --- bet you use lots of parenthesis
too, don't you... What university did you say you attended?... Yeah, I'll
just *bet* you did..."

Even "lint" likes parenthesis, that must mean something.

output:

}-1.129-> ./maze
7
._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
| ._| . . ._| | |_._._. . ._|_._._._._. ._|_. ._|_._. ._| | . ._|_. | . ._._. |
| ._|_| |_. | | | | ._._|_._|_._. . |_. | | | ._._| |_._._._| | ._. ._| . . |_|
|_._._._. | ._|_. ._._._. | | ._. |_._. . | ._._| |_. | . ._._._. |_. | |_|_| |
| | . |_._| . ._._._| ._._. ._._| | | |_| . | |_. . ._|_|_| ._._. |_._|_| . | |
| | |_| |_._| | ._. . | | |_._._| | | | | |_|_. . |_| . | |_| . . ._|_. |_|_. |
|_. | |_._._._|_. |_|_| ._._| ._._. ._| . . | ._|_. ._| . ._|_| |_. . | | | | |
|_._._._._._._._._._|_._._._._|_._._|_._|_|_._._|_._._|_|_._._._._|_|_._._._._|
|}-1.233->

---------------original program as posted:

}-1.130-> cat maze.c
char*M,A,Z,E=40,J[40],T[40]; main(C){for(*J=A=scanf(M="%d",&C);--E;J[E]=T[E]=E)printf("._");for(;(A-=Z=!Z)||(printf("\n|"),A=39,C--);Z||printf(M))M[Z]=Z[A-(E=A[J-Z])&&!C&A==T[A]|6<<27<rand()||!C&!Z?J[T[E]=T[A]]=E,J[T[A]=A-Z]=A,"_.":" |"];}

---------------lint's impression of the original code above:

}-1.233-> lint maze.c
maze.c
==============
(1)  warning: precedence confusion possible: parenthesize!
(1)  warning: main() returns random value to invocation environment
==============
function returns value which is always ignored
    printf

---------------reformatted program:

}-1.187-> cat ./maze+.c
main()
{
    int   C;  /* number of rows of cells */
    char *M;
    char  A, Z, E=40, J[40], T[40];
    
    for(*J = A = scanf(M = "%d", &C) ; --E ; J[E] = T[E] = E) printf("._");
    /* top line of first row has been printed
     * J holds 1,1-39, T holds 0-39, A is 1, E and Z are 0, M -> "%d"
     *
     * ONE LINE NESTED LOOP
     * (the loop I understand, the contents are another matter entirely)
     *
     * Z oscillates between 0 (initially) and 1.
     * On the end of all passes except the last, A=39, C--, "\n|" prints.
     * On the end of Z==1 passes, A drops, and M is printed.
     * On the end of passes where Z==1, M is printed.
     * The loop is terminated when C is dropped to 0.
     */
    for( ; (A -= Z = !Z) || (printf("\n|"), A=39, C--) ; Z || printf(M))
        /* The abuse of M requires a GCC compile flag: -fwritable-strings
         *
         * Constant: Z  A  J  Z  C  T  J  A[J-Z]
         * Variable: E  M[0]  M[1]  T[A]  J[see below]
         * Derivations:
         *        E <<< A[J-Z]   each pass
         *     T[E] <<< T[A] <<< A-Z    \
         *  J[T[A]] <<< E               |__only passes printing "_."
         *   J[A-Z] <<< A               /
         * M[Z] is set to "_." or " |".  The 1st has side-effects
         */
        M[Z] = 
            Z[
                  A - ( E = A[J-Z] )
                &&
                  /* seems (6<<27 < rand()) is true app. 59% of the time */
                  /*   /-------\  //-----\ -------\  */
                  !C & A == T[A] | 6 << 27 < rand()
                ||
                  !C & !Z
              ? J[T[E]=T[A]] = E , J[T[A]=A-Z] = A, "_."
              : " |"
              ];
}

P.S.  If anyone ever does figure this puppy out...send me mail, eh?
------------------------------------/\----------------------------------------
Seo:  Harp[@Mcc.Com]               /  \/\ ^*^           Christopher North-Keys
Tha mi gu trang a'cluich.         /    \ \         Assoc. Systems Analyst, MCC
--------------------------------(disclaimer)----------------------------------



More information about the Comp.lang.c mailing list