Rules:
- a. The comma operator
,shall not be used within variable declarations.
Example:
char * x, y; // Was y intended to be a pointer also? Don’t do this.
...
char *x, *y; // This is correctly done.Reasoning:
The cost of placing each declaration on a line of its own is low. By contrast, the risk that either the compiler or a maintainer will misunderstand your intentions is high.
Enforcement:
This rule shall be enforced during code reviews.
Rules:
- a. It is a preferred practice that the shortest (measured in lines of code) of the if and else if clauses should be placed first.
- b. Nested
if...elsestatements shall not be deeper than two levels. Use function calls or switch statements to reduce complexity and aid understanding. - c. Assignments shall not be made within an
iforelse iftest. - d. Any
ifstatement with anelse ifclause shall end with anelseclause.
Example:
if ( NULL == p_object ) {
result = ERR_NULL_PTR;
} else if (p_object = malloc(sizeof(object_t))) { // No assignments!
...
} else {
// Normal processing steps, which require many lines of code.
...
}Reasoning:
Long clauses can distract the human eye from the decision-path logic. By putting the shorter clause earlier, the decision path becomes easier to follow. (And easier to follow is always good for reducing bugs.) Deeply nested if...else statements are a sure sign of a complex and fragile state machine implementation; there is always a safer and more readable way to do the same thing.
Enforcement:
These rules shall be enforced during code reviews.
Rules:
- a. The
breakfor eachcaseshall be indented to align with the associatedcase, rather than with the contents of thecasecode block. - b. All
switchstatements shall contain adefaultblock.- i. The
defaultcase shall have one empty line beforehand.
- i. The
- c. Any
casedesigned to fall through to the next shall be commented to clearly explain the absence of the correspondingbreak.
Example:
switch (err)
{
case ERR_A:
...
break;
case ERR_B:
case ERR_C: // Also perform the steps for ERR_C.
...
...
break;
default: // One empty line before `default` case.
...
break;
}Reasoning:
C’s switch statements are powerful constructs, but prone to errors such as omitted break statements and unhandled cases. By aligning the case labels with their break statements it is easier to spot a missing break.
Enforcement: These rules shall be enforced during code reviews.
Rules:
- a. Magic numbers shall not be used as the initial value or in the endpoint test of a
while,do...while, orforloop. - b. With the exception of the initialization of a loop counter in the first clause of a for statement and the change to the same variable in the third, no assignment shall be made in any loop’s controlling expression.
- c. Infinite loops shall be implemented via controlling expression
while( 1 );. - d. Each loop with an empty body shall feature a set of braces enclosing a comment to explain why nothing needs to be done until after the loop terminates.
Example:
// Why would anyone bury a magic number (e.g., “100”) in their code?
for (int row = 0; row < 100; row++) {
// Descriptively-named constants prevent defects and aid readability.
for (int col = 0; col < NUM_COLS; col++) {
...
}
}Reasoning:
It is always important to synchronize the number of loop iterations to the size of the underlying data structure. Doing this via a descriptively-named constant prevents defects that result when changes in one part of the code, such as the dimension of an array, are not matched in other areas of the code.
Enforcement:
These rules shall be enforced during code reviews.
Rules:
- a. The use of
gotostatements shall be restricted. - b. C Standard Library functions
abort(),exit(),setjmp(), andlongjmp()shall not be used.
Reasoning:
Algorithms that utilize jumps to move the instruction pointer can and should be rewritten in a manner that is more readable and thus easier to maintain.
Enforcement:
These rules shall be enforced by an automated scan of all modified or new modules for inappropriate use of forbidden tokens. To the extent that the use of goto is permitted, code reviewers should investigate alternative code structures to improve code maintainability and readability.
Rules:
- a. When evaluating the equality of a variable against a constant, the constant shall always be placed to the left of the equal-to operator (
==).
Example:
if ( p_object == NULL ) { // This is not OK!!!
return ( ERR_NULL_PTR );
}
...
if ( NULL == p_object ) { // This is OK!!!
return ( ERR_NULL_PTR );
}Reasoning:
It is always desirable to detect possible typos and as many other coding defects as possible at compile-time. Defect discovery in later phases is not guaranteed and often also more costly. By following this rule, any compiler will reliably detect erroneous attempts to assign (i.e., = instead of ==) a new value to a constant.
Enforcement:
Many compilers can be configured to warn about suspicious assignments (i.e., located where comparisons are more typical). However, ultimate responsibility for enforcement of this rule falls to code reviewers.
Version : 1.0.0
- 1.0.0 / Document initial version created by Strahinja Jacimovic
