Writing Bug-Free C Code
A Programming Style That Automatically Detects Bugs in C Code
by Jerry Jongerius / January 1995
<< Previous Index Next >>
Chapter 8: Style Guide

8.1 Commenting Code
8.2 Indentation Rules/Examples
  8.3 Defining Auto Variables
8.4 Avoid Using the Comma Operator

Writing a style guide is hard because every programmer has his or her own way of doing things. Despite this problem, I feel that it is important that a style guide exist in written form at any organization. The rest of this chapter describes the style that I use to write code.

8.1 Commenting Code

Every module and every function has a comment header. The layout of a module is covered in Chapter 6.

Within a function there are two basic forms of comments that I use. They are the Endline comment and the Inline comment.

8.1.1 Endline Comments

Endline comments are used almost exclusively to document variable declarations. These declarations can be auto variable definitions or structure member declarations.

An endline comment uses the C++ style single line comment // (two slashes) and begins in column 41.

EndLine comment examples, using C++ //
typedef struct {
    int x;                    // the x coordinate of the point
    int y;                    // the y coordinate of the point
    } POINT;

int main(void)
{
    int nCpuBusy;             // how busy is the cpu
    (code body)
    return 0;
}

If you do not have access to a C++ compiler, use the standard C /* */ comment form as follows.

EndLine comment examples, using /* */
typedef struct {
    int x;                    /* the x coordinate of the point */
    int y;                    /* the y coordinate of the point */
    } POINT;

int main(void)
{
    int nCpuBusy;             /* how busy is the cpu */
    (code body)
    return 0;
}

8.1.2 Inline Comments

The inline comment is used to comment a small section of code within a function.

Inline comment example
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    static char buffer[9000]; /* buffer for input line */
    long lLineCount=0;        /* number of lines read  */
    /*--- Count the number of lines in the input ---*/
    while (safegets(buffer,sizeof(buffer))) {
        ++lLineCount;
        }
    /*--- Display the total line count ---*/
    printf( "Number of Lines = %ld\n", lLineCount );
    return 0;

} /* main */

The inline comment starts with /*--- and ends with ---*/ and always has one blank line preceding it.

A technique that I use when writing the inline comments of a function is to pretend that all the code in the function has been removed. Would reading the remaining inline comments be helpful and meaningful? Try to write the inline comments so that they would make sense in this context.

8.2 Indentation Rules/Examples

All of my indentation levels are based on four spaces. So the first indentation level starts in column 5, the next indentation level starts in column 9, and so on.

8.2.1 Functions

A function must always consist of a comment header followed by a blank line and the function body.

Function template
/*pf--------------------------------------------------------------
 *
 *  DESCRIPTION: (Short Description)  programmers-initials
 *
 *    (A long description of the function)
 *
 *  ARGUMENTS:
 *
 *    Arg1 - Arg1 description
 *    ...
 *    ArgN - ArgN description
 *
 *  RETURNS:
 *
 *    (A description of the return value)
 *
 *  NOTES:
 *
 *    (optional notes section)
 *
 *--------------------------------------------------------------*/

type APIENTRY FunctionName( arguments )
{
    type variable1;           /* Comment */
    type variable2;           /* Comment */
    /*--- Comment ---*/
    (block of code)
    /*--- Comment ---*/
    (block of code)
    ...

} /* FunctionName */

The begin and end brace of a function are on separate lines in column 1. In addition, the ending brace is followed by a space and a comment that is the function name.

Local variable declarations and the main code in the function are at the first indentation level. The local variables of the function, if any, are declared first and always have endline comments.

The code within the function uses inline comments to document the code and follows the blank line before an inline comment rule. There is always one blank line after the last line of code and before the ending brace of the function.

8.2.2 The IF Statement

The if statement begins with one line containing the if statement, the expression and the begin brace. There is one space after the if statement and before the begin brace. The body of the if statement and the ending brace are at the next indentation level.

if statement template
/*--- Comment ---*/
if (expression) {
    statement;
    ...
    }

The if statement always has a begin brace and an end brace, even when followed by only a single statement.

8.2.3 The IF/ELSE Statement

The if statement begins with one line containing the if statement, the expression and the begin brace. There is one space after the if statement and before the begin brace. The body of the if statement and the ending brace are at the next indentation level.

The else statement begins at the same indentation level as the if statement and is followed by a space and a begin brace. The body of the else statement and the ending brace are at the next indentation level.

if/else statement template
/*--- Comment ---*/
if (expression) {
    statement;
    ...
    }
/*--- Else comment ---*/
else {
    statement;
    ...
    }

The if statement and the else statement always have a begin brace and and end brace.

8.2.4 The WHILE Statement

The while statement begins with one line containing the while statement, the expression and the begin brace. There is one space after the while statement and before the begin brace. The body of the while statement and the ending brace are at the next indentation level.

while statement template
/*--- Comment ---*/
while (expression) {
    statement;
    ...
    }

The while statement always has a begin brace and an end brace.

8.2.5 The DO/WHILE Statement

The do statement begins with one line containing the do statement, a space and the begin brace. The rest of the do/while statement is at the next indentation level. The do/while ends with an end brace, the while statement and the expression on one line. There is one space after the ending brace and after the while statement.

do statement template
/*--- Comment ---*/
do {
    statement;
    ...
    } while (expression);

8.2.6 The FOR Statement

The for statement begins with one line containing the for statement, the three expressions and the begin brace. There is one space after the for statement and before the begin brace. The three expressions are contained in parentheses and are separated by a semicolon and space.

for statement template
/*--- Comment ---*/
for (loop=0; loop<nMax; ++loop) {
    statement;
    ...
    }

The for statement always has a begin brace and an end brace.

8.2.7 The SWITCH Statement

The switch statement begins with one line containing the switch statement, the expression and the begin brace. The body of the switch statement and the ending brace are at the next indentation level.

The body of the switch statement contains case statements and a default statement. Each case and default are on a new line with the body of each case and optional default at a new indentation level.

switch statement template
/*--- Comment ---*/
switch (expression) {
    case constant:
        statement;
        ...
        break;
    case constant: {
        statement;
        ...
        break;
        }
    default:
        statement;
        ...
        break;
    }

If a case uses local variables, begin and end braces are used. The begin brace is on the same line as the case and begins after the colon followed by a space. The end brace is on a new line after the break at the same indentation level as the body of the case.

8.3 Defining Auto Variables

Auto variables should be defined one per line. Do not use the comma to define multiple variables per line. Consider the following.

Bad use of comma in auto variable definition
void Testing( void )
{
    char *pBeg, pEnd;            /* comment */
    ...

} /* Testing */

Correct way to define auto variables void Testing( void ) { char *pBeg; /* comment */ char *pEnd; /* comment */ ... } /* Testing */

The problem with this code is that the data type of pBeg is char* and the data type of pEnd is char, which is more than likely not what was intended. The preferred way to define auto variables is one per line.

8.4 Avoid Using the Comma Operator

The comma operator is typically used to treat two expressions as one. This can be useful in situations where only one expression is allowed. The value of the two expressions separated by the comma operator is the value of the second expression.

Comma operator syntax
expression, expression

However, using the comma operator can lead to code that is hard to read and maintain. It is best to avoid using it.

One possible exception is in macros where it is important that the macro be viewed by the programmer as a single expression. If you cannot accomplish everything in one expression, do you give up? In cases like this, it is important to avoid having to change the syntax of how a macro is used and usage of the comma operator is allowed.


Copyright © 1993-1995, 2002-2024 Jerry Jongerius
This book was previously published by Pearson Education, Inc.,
formerly known as Prentice Hall. ISBN: 0-13-183898-9