Notes on Formatting Style

This section touches on some fairly religious issues, and formatting generally does not affect the quality of the code; only its appearance. Well-formatted code, however, can help readability and therefore help in debugging and reviewing. I've gone through many different formatting styles in the last couple years, and the following is a summary of my current one. Whatever your style, remember to always use the style of a file you're editing -- inconsistent style is worse than bad style.

Indentation

Indent each logical block 4 spaces. Two spaces aren't enough, especially when trying visually to line up blocks. Three spaces aren't even a power of two. Eight-space tabs are fairly standard, and this indentation style is used very often, e.g., the entire UNIX kernel. One problem with 8-space tabs, however, is that you quickly find yourself running off the end of the line, especially with switch statements that take up two indentations. My current solution is to set vi's shiftwidth to 4, then use ^T and ^D to indent and unindent. Emacs users can use C mode to indent the same way. Keep vi's tabstops to 8 so that printouts come out right.

While we're on the issue, I'll say a few things that are obvious to most people. *Always* indent the lowest-level block of a function. Some people don't indent the first level (it is flush-left); not only does it make the code unreadable and functions hard to find, but programs that don't parse C code well (such as ctags(1)) often make errors and think that "while" and "for" are functions.

Also, make sure that no lines wrap around to the next line. This is not only an aesthetic issue, but wrapping causes some text to appear at the beginning of the line, which makes scanning for the beginning and end of functions more difficult.

Braces

Always put braces around blocks, even if the block is only one line long. The reasons for this are given in the first section of this document. Once that's done, there's no point in putting the open brace on the next line, so go ahead and put it on the same line. This makes the code look good both when indenting and unintending:

    if (t >= 0.0) {
	while (!done) {
	    ...;
	}
    }
I'll (very) occasionally put the block on the same line as the "if", but only if it helps readability:
  if (R > 1) { R = 1; }
  if (G > 1) { G = 1; }
  if (B > 1) { B = 1; }
is clearer than:
  if (R > 1) {
      R = 1;
  }
  if (G > 1) {
      G = 1;
  }
  if (B > 1) {
      B = 1;
  }
Note that I still use braces around the block.

Spacing

I always put a space between the function name and the open parenthesis. There's no specific reason for this except that I wanted to be consistent and this aired the code out a bit better. I also always put a space around operators that have lower precedence than the unary group. That is, there are no spaces around -> or "." (member-of), or around unary operators. All others are spaced out, e.g.:
    if (a == b || c <= d + 5) ...
I make a few exceptions to this rule, especially when it makes the appearance reflect the meaning of the code better, e.g.:
    dist = sqrt (x*x + y*y + z*z);
which I think looks cleaner and better than:
    dist = sqrt (x * x + y * y + z * z);
I don't usually put spaces immediately inside parentheses because I find this makes it harder to read:
    dist = sqrt ( x*x + y*y + z*z );
or
    if ( a == b || c <= d + 5 ) ...
I also line up variables names in definition sections and structure declarations, e.g.:
    int			x, y, z;
    struct blah		a, *b;
    unsigned int	i, j;
and:
    struct point {
	int	x, y, z;
	float	r, g, b;
    };
It's also a good idea to make good use of vertical spacing. Specifically, use one blank line between logical parts of functions and two blank lines between logical parts of source files (e.g., between functions).

Comments

For consistency, most comments should look like the Berkeley-style block:
    /*
     * This is a comment.  It can go on for a while and looks clean.
     * Even one-line comments should be written this way because they
     * stand out.  If a comment doesn't need to stand out, then it's
     * probably not worth putting in at all.
     *
     * Several paragraphs can go in one comment.
     */
These are easy to format with modern editors like vim. Exceptions are short descriptions of variables or structure elements:
    struct node {
	char		*name;	/* Name of customer (or NULL)	*/
	int		age;	/* Age in years			*/
	struct node	*left;	/* Pointer to left child	*/
	struct node	*right;	/* Pointer to right child	*/
    };
and little reminders:
    xratio  =  yoffset / tanfov;       /* Yes, this is yoffset */
    yratio  = -yoffset / tanfov;
Avoid obvious comments:
    /*
     * Return an error.
     */

    return ERROR;
Always document your data structures. The program will often explain itself once the data structures are clear.

Function declarations

Needless to say, you should always use ANSI-style function declarations. Some people write the functions this way:
    int main (
	int	argc,
	char	*argv[])
    { ...
but I still prefer this more compact form:
    int main (int argc, char *argv[])
    { ...
both because you can cut-and-paste it to the header file and because it reflects more closely the way it will look when you call it. My jury's still out on this one. The former way is better when putting in-line comments for each parameter.