
The Ten Commandments for C Programmers (Annotated Edition) - b-man
http://www.lysator.liu.se/c/ten-commandments.html
======
jws
I wonder when this was written. The earliest reference I found was June 1993
in an AUUG (Australian Unix Users Group) newsletter.
[http://books.google.com/books?id=lbsmK77EVU4C&lpg=PA1...](http://books.google.com/books?id=lbsmK77EVU4C&lpg=PA1&pg=PA36#v=onepage&q&f=false)

1) _run lint_ : Not anymore. But then I'm a -Wall -Werr kind of guy and I
visit Clang.

2) _don't follow NULL_ : Well, obviously.

3) _cast function arguments to the expected type_ : Not important now that the
types are in the declarations. But if you don't force that, then yes. Got that
right. Just as people got complacent with 32bit data and address, BANG!

4) _declare return types for functions_ : That insanity has passed from
practice.

5) _check bounds_ : Yep, still causing exploits today.

6) _check error codes_ : Yep, and triples is about right for library/system
call intensive code. But the first time fclose() returns an error and you
catch it you will be happy.

7) _don't re-implement the library_ : Beating a modern C library is hard. But:
if you have a special case, you can still get a significant gain by exploiting
that, after you have profiled and know you aren't engaging in petty puffery.
(It should be mentioned that the author is the Henry Spencer that wrote and
distributed a regex library back in the days of ftp.)

8) _use K &R brace styles_: I care so little for brace styles I can't tell you
which is K&R after writing hundreds of thousands of lines of C code.

9) _external symbols must be unique in the first 6 characters_ : Ha ha! Good
riddance SCO, the last system I met where that was an issue (in _ar_ libraries
only I think.)

10) _all the world's a vax_ : s/VAX/x86/ e.g. I keep a PPC (byte order) and an
ARM (char is unsigned) just to keep me honest on this.

~~~
JoachimSchipper
Two additions:

1) -Wall -Werr does not note type conversions (indeed, it could not, because
they are necessary - just dangerous. -1 < 0U is usually _not_ true!)

3) Casting is very much necessary with function taking a variable number of
arguments.

But yes, modern tools and C90/C99 help a lot.

~~~
nitrogen
gcc -Wall does warn about comparison between signed and unsigned types, as
well as comparisons that are always true/false due to limited type range.

~~~
JoachimSchipper
But you can't really enable those warnings if you want to use -Werr, right?

And I've always found the "always true/false due to limited range of data
type" to be counterproductive. Something like

    
    
        int i;
        ...
        assert(i <= SSIZE_MAX);
        f(i);
    

can make sense, but will cause gcc to complain if int and ssize_t happen to be
the same size.

~~~
nitrogen
There are ways of fixing the warnings so you can use -Werr. For
signed/unsigned, just change the type of one side of the comparison, or cast
to whichever type is most correct for the comparison while manually making
sure that you won't have any range issues. For your limited range example, you
could probably use the preprocessor:

    
    
          ssize_t i;
      #if SSIZE_MAX != INT_MAX
          assert(i <= INT_MAX);
      #endif /* SSIZE_MAX != INT_MAX */
          f(i);

------
johnl87
Little known fact...the only reason the brace is on the same line as the
function declaration is because K&R just wanted to save space in the code
listings.

~~~
Seth_Kriticos
Um, no, K&R braces after function declaration are in the next line, because
they are special.

Braces after if, for, while, switch, etc. are on the same line, and yes, it
was to save space on the 80x24 screen.

Get a copy of "The C Programming Language, Second Edition". It's right in
there. It's the only technical computer book I know that is still accurate
after more than twenty years.

I also recommend reading the Linux kernel style guide
<http://www.kernel.org/doc/Documentation/CodingStyle> . It's fun to read and
has some good points. Sticks quite close to K&R.

~~~
Jach
I agree it's fun to read and has some good points, but it's obvious it's meant
only for really imperative-styled C that you'd expect to find in the kernel.
e.g.:

> ... if you need more than 3 levels of indentation, you're screwed anyway,
> and should fix your program.
    
    
      class A:
        def foo(self):
          while cond:
            if othercond:
              bar()
    

Uh oh, four indentation levels!

~~~
Seth_Kriticos
Well, yes. But the style guide was written for plain C, in which the program
logic starts at the first indentation in functions.

In Python you have very different characteristics, and have to adapt styles.

You should not get deeper than 3 logic indentations on function level there
either, though.

And from my experience, 8 character tabs (with the article you cited actually
starts with) are still workable in Python, at least for me.

------
lisper
> Thou shalt not follow the NULL pointer

How much pain and misery could be avoided if hardware manufacturers would
simply design computers so that memory location 0 was hard-wired to always
contain a 0.

Sigh.

~~~
pornel
That doesn't work if you expect struct or array at 0.

IMHO a better solution is to have a type system that has non-NULLable types,
and/or use language that inserts NULL checks automatically (and optimizes them
away where they're redundant).

~~~
lisper
> That doesn't work if you expect struct or array

Ah, good point.

------
ldng
Any chance someone "translate" it to plain modern english for us poor
foreigners ? I find it quite hard to read for non-natives, not even talking
about cultural references.

------
wyclif
This is ancient. It's so old I can't remember the last time I saw it, but I'm
glad somebody remembered to submit it just for kicks.

------
palish
_"Also, contrary to the beliefs common among the more backward inhabitants of
the Polluted Eastern Marshes, `NULL' does not have a pointer type, and must be
cast to the correct type whenever it is used as a function argument."_

Why? This seems like a waste of thought...

~~~
glhaynes
I had the same question. Also, I'm having trouble guessing what the Polluted
Eastern Marshes would be here… IBM (New York)? Judging from the rest I
wouldn't _guess_ that IBM was too into C when it was written, but it's hard to
tell. So … Japan? Nah…

~~~
spc476
The Polluted Eastern Marshes would be New Jersey. More specifically, Murray
Hill, New Jersey, home of Bell Labs, and Unix.

~~~
glhaynes
Ahh, thanks!

