Menu

Coding Style

Coding Style Guidelines

  1. Rationale
  2. White Space
  3. Indentation
  4. Comments
  5. Identifiers
  6. Brackets/Braces
  7. Miscellaneous

Rationale

There are many opinions on how to properly format C code, each with their own merits. A certain amount of leeway in terms of personal personal preference is fine, however there are various reasons why it is desirable to set certain conventions. Some of those reasons are as follows:

  • Readability: Certain aspects of the formatting can greatly influence the ease with which others can understand your code.
  • Consistency: Having common conventions in place throughout the codebase leads to less confusion when looking at different parts of the codebase. It also looks better.
  • Esthetics: The code just looks better when formatted consistently.
  • White space: A few conventions with respect to white space can prevent patches and version control changes from including lines with no functional differences, but different white space.

For these reasons and more, this page has been prepared to provide various guidelines for source code formatting when editing or adding TwoCan sources.

White Space

Whitespace should generally be used to improve the clarity and readability of the code. Excess whitespace that does not aid clarity should be avoided. Some guidelines for the use of whitespace in various situations are listed below:

  • Use spaces instead of tabs everywhere, unless the difference is vitally important. For example, don't use tabs in C source, but they're fine in makefiles where make requires them.
  • Remove trailing spaces from the ends of lines.
  • Stick to Unix-style line endings.
  • Do not add space between the parentheses for a function's parameter list and the function name.
  • Place spaces around operators, except between unary operators and the value they apply to or between an operator and a bracket or parenthesis.
  • Leave spaces after the commas between parameters in function headers.
  • Do not add spaces between parentheses and the expressions within them, except to aid readability when several sets are nested.
  • Don't mess with the white space in existing sources unless it makes a notable difference to readability. When formatting of existing code is changed, add it as a separate commit that changes formatting only.

Blank lines should be used mainly to separate logically distinct elements in the code. They should also help relate comment blocks to the items they describe. Some recommended places to insert blank lines are as follows:

  • Around structure definitions (with the descriptive comment included)
  • Around function definitions
  • Between comment blocks that discuss different topics
  • Between groups of related statements, such as between a groups of statements that perform different logical steps in a process.
  • Between paragraphs in a comment block

Some places to avoid blank lines are as follows:

  • Between a block's braces and the statements within it
  • Between a comment and the item it describes

Indentation

Blocks should be indented by two spaces. This includes function bodies, loop bodies, member lists in struct/enum/union definitions, and elements in array initializers when not on a single line.

When indenting a block, indent the contents of the block only; do not indent the braces. When the brace is the first thing in a line, it should be aligned with the keyword or identifier associated with the block (if there is one).

When a statement spans multiple lines, the first line should be indented normally. Successive lines should be indented at least four additional spaces, or more if it helps (to keep identifiers aligned, or to keep the remainder of the statement aligned with the assignment operator, etc.).

When a function parameter list is very long, it can be split over several lines. In this case, try to keep the parameters aligned with each other (at their left sides).

In large array initializers, with several elements on each line, try to keep the
columns aligned at their left edges (though not necessarily evenly spaced). Try
to choose a convenient number of columns that makes it easy to determine the indexes of the elements by looking at the initializer, such as a power of two or a multiple of ten. Use comments to number rows or groups of rows with the first array index in the row or row group to help with this.

Comments

Comments are to be used almost exclusively for documentation and aiding comprehension of the code. Many of them will contain Doxygen markup; refer to the Doxygen documentation (elsewhere) for the syntax. The following guidelines should be followed for comments:

  • Avoid comments that do not clarify and document the code.
  • Source files should include a comment block near the the top of the file to document the purpose of the file (use the \file tag).
  • Use the /** or /// syntax for documentation comments, and start Doxygen tags with a backslash.
  • Document all functions and structures in (Doxygen style) documentation comments, including parameters and return values.
  • Document structure members, preferably with a short line comment at the end of the same line. If the description needs a lot of space, place the comment on its own line(s) preceding the member declaration instead.
  • Comments within functions that describe how the function's code works, rather than what the function does and how to use it, are useful and should be included whenever a piece of code may be unclear. However, comments like these should be ordinary comments, not documentation comments. What "unclear" means is, of course, subjective.
  • A little humour here and there is fine, as long as it doesn't cause confusion.

Identifiers

For most identifiers, just use descriptive names. Abbreviations and acronyms are fine as long as they're reasonably obvious. Use camelCase when identifiers are formed from several words, starting with lowercase for variable and function names or uppercase for types and function names based on type names.

For certain types used for objects encapsulating data and related functions, additional conventions are to be followed:

  • Members that are not meant to be directly accessed should be prefixed with the (admittedly arbitrary) prefix "f_".
  • The names of functions should begin with the type name, followed by an underscore.
  • Except for constructors and destructors, functions should be called through pointers in the struct which follow the normal naming conventions (no type prefix).

Brackets/Braces

Curly Braces

The contents of statement blocks should be indented, but not the braces. This applies to loop bodies, function bodies, struct definitions, multiline array initializers, stand-alone statement blocks, pretty much anything in curly braces that isn't entirely on one line.

Blocks associated with control structures should have their braces on the same lines as the adjacent keywords or test expressions for those control structures.

Opening braces for multiline array or struct initializers should not be placed on separate lines; doing so for the closing braces is optional.

The braces of function bodies should be on their own lines.

/* Brace opening struct body is NOT on a new line */
struct SomeStruct {
  int   mbrA;
  int   mbrB;
};

/* Brace opening array initializer is also not on a new line */
/* Note that in this example, the left-side comments are indented

 * by the usual amount, rather than the actual element values -- we
 * indent for readability, so its the visual effect that matters. */
int anArray[0x20] = {
  /*            0/8   1/9   2/A   3/B   4/C   5/D   6/E   7/F */
  /* 00-07 */  1234, 2345, 3456, 4567, 5678, 6789, 7890, 8901,
  /* 08-0F */  9012,  123, 1234, 2345, 3456, 4567, 5678, 6789,
  /* 10-17 */  7890, 8901, 9012,  123, 1234, 2345, 3456, 4567,
  /* 18-1F */  5678, 6789, 7890, 8901, 9012,  123, 1234, 2345
};

int someFunc(int x)
{
  /* For function bodies, opening brace is on a new line. */
  /* Braces are not indented, but the contents are. */
  int y,z;

  if (x > 0) {
    /* Braces stay with adjacent

     * branch/control structure keywords */
    y = x;
    z = 2 * x;
  } else {
    /* braces stay with 'else' too */
    y = 0;
    z = 2 * x;
  }

  return y + z;
}

Parentheses

Parentheses should not have spaces added on the inner side unless it aids clarity (for example, to make the grouping clearer with nested parentheses).

A large expression with many nested sets of parentheses may be split onto multiple lines so that the different nesting levels can be shown with indentation, provided that all the additional lines are noticeably indented.

/* no spaces around parentheses normally */
x = ((y + 7) * (32 * x + 1));

/* An exception can be made for deeply nested sets.. */
qrs = ( ((x + y) / 2) * (3 - ((y + 42) / z)) ) + 8;

/* ...or if it gets really complex, you might indent.  Note that although

 * the lines don't wrap at any particular nesting level, the indentation
 * of the start of each line matches the nesting level. */
if ( ( (x + y + foobar(52, x + 4) * 17 > 302) &&
       (x + y + z + t + u + v < 77) ) ||
     ( (x > y) && (y > z) && (z > t) ) ) {
  /* ... */
}

No spaces should be added between a function name and the parentheses of its parameter list: So use someFunction(5); and not someFunction (5);.

Square Brackets

Do not add spaces between square brackets and their contents, between brackets and the identifier or expression they index, or between adjacent sets of square brackets. For example:

arr[i][j] = (ptr + i)[j % 10];

Miscellaneous

TODO


Related

Wiki: Developer Info

MongoDB Logo MongoDB