Coding Conventions

Go Home | Go Back to Tips Page



Introduction

The following coding conventions are from Jack Ganssle's book The Art of Designing Embedded Systems, ISDN 0-7506-9869-1. Although I don't follow his conventions strictly, I do think some of them extremely valuable for writing good-looking codes. However, I disagree with Jack in some points, for example, I don't think it is a good idea to put a space before and behind a star in declare a pointer. I prefer

char *ptr_char,

instead of

char * ptr_char

and I didn't see the point why he insist using spaces instead of tabs to indent. I like tabs, because it can save so many keytrokes. Nowadays, it is very hard to find a editor not recognizing the tabs (maybe the SimpleText? Fortunately, I never use SimpleText to write program codes, althought I use it for writing html codes).

Go to Top


General

No line may ever be more than 80 characters.

Don't use absolute path names when including header files. Use the form #include <module/name> to get public header files from a standard place.

Never, ever use "magic numbers." Instead, first understands where the numbers comes from, then define it in a constant, and then document your understanding of the number in the constant's declaration.

Go to Top


Spacing and Indentation

Put a space after every keyword, unless a semicolon is the next character, but never between function names and the argument list.

Put a space after each comma in argument list and after the semicolons separating expressions in a for statement.

Put a space before and after every binary operator (like +, -, etc.). Never put a space between a unary operator and its operand (e.g. unary minus).

Put a space before and after pointer variants (star, ampersand) in declarations. Precede pointer variants with a space, but have no following space, in expressions.

Indent C code in increments of two spaces. That is, very indent level is two, four, six, etc. spaces. Indent with spaces, never tabs.

Always place the # in a preprocessor directive in column 1.

Go to Top


C Formatting

Never nest IF statements more than two deep; deep nesting quickly becomes imcomprehensible. It's better to call a function, or even better to replacement complex IFs with a SWITCH statement.

Place braces so the opening brace is the last thing on the line, and place the closing brace first, like:

  if (result > a_to_d) {
    do a bunch of stuff
  }

Note that the closing brace is on a line of its own, except when it is followed by a continuation of the same statement, such as

  do {
    body of the loop
  } while (condition);

When an if-else is nested in another if statement, always put braces around the if-else to make the scope of the first if clear.

When splitting a line of code, indent the second line like this:

  function(float arg1, int arg2, long arg3,
           int arg4)

or,

  if (long_variable_name && constant_of_some_sort ==
  2
      && another_condition)

Use too many parentheses. Never let the compiler resolve precedence; explicitly declare precedence via parenthesis.

Never make assignments inside if statements. For example, don't write:

  if ((foo = (char *) malloc(sizeof *foo)) == 0)
    fatal("virtual memory exhausted");

instead, write:
  foo = (char *) malloc(sizeof *foo);
  if (foo == 0)
    fatal("virtual memory exhausted");

If you use #ifdef to select among a set of configuration options, add a final #else clause containing an #error directive so that the compiler will generate an error message if none of the options has been defined:

  #ifdef sun
  #define USE_MOTIF
  #elif hpux
  #define USE_OPENLOOK
  #else
  #error unkown machine type
  #endif

Go to Top


Assembly Formatting

Tab stops in assembly language are as follows

  • Tab 1: column 8
  • Tab 2: column 16
  • Tab 3: column 32

Note that these are all in increments of 8, for editors that don't support explicit tab settings. A large gap--16 columns--is between the operands and the comments.

Place labels on lines by themselves, like this:

label:
        mov     r1, r2          ; r1=pointer to I/O

precede and follow comment blocks with semicolon lines:

;
; Comment block that shows how comments stand
; out from the code when preceded and followed by
; "blank" lines.
;

Never run a comment between lines of code. For example, do not write like this:

        mov     r1, r2          ; Now we set r1 to the value
        add     r3, [data]      ; we read back in read_ad

Instead, use either a comment block, or a line without an instruction, like this:

        mov     r1, r2          ; Now we set r1 to the value
                                ; we read back in read_ad
        add     r3, [data]

Be wary of macros. Though useful, macros can quickly obfuscate meaning. Do pick very meaningful names for macros.

Go to Top


Go Home | Go Back to Tips Page