| Coding Guidelines |
|
Generic Guidelines |
|
|
Formatting |
|
|
The primary reason that we concern ourselves with formatting is to make the code more
humanly understandable.
White Space
White space, which is defined as the space surrounding statements, expressions, and
comments, is important in enhancing the readability of code. As an example of what white
space can do to help readability, the following is a simple function that many beginning C
programmers write to take an integer and convert it into a string of numeric characters.
We have been generous in at least keeping basically single statements on a line by them
selves.
void itoa(int n,char s[]){
int i,sign;
if((sign=n)<0)n=-n;
i=0;
do{s[i++]='0'+n%10;}while(0<(n/=10));
if(sign<0)s[i++]='-';
s[i]=EOS;
reverse(s);
} |
Without changing anything but adding white space (and a couple of carriage-returns) the
function becomes much more understandable.
void itoa
(
int n,
char s[]
)
{
int i, sign;
if ( (sign = n) < 0 )
n = -n;
i=0;
do
{
s[i++] = '0' + n % 10;
} while ( 0 < (n /= 10 ) );
if ( sign < 0 )
s[i++] = '-';
s[i] = EOS;
reverse(s);
}
|
More work should be done on this function to improve its readability, such as improving
names and adding comments, but before we added white space it was difficult to tell what
needed to be done to improve the function. For that matter it was difficult to tell what
the function did.
Indentation
Each indentation should be a four character tab
|
Each indentation should be four columns. The most
important aspect of indentation is to be consistent. |
Indent one level for each new level of logic
|
Indentation is used to clarify the control flow through
the code.
if ( 0 == gameOver )
if ( YOU == playerToMove )
printf( "Your move\n" );
|
|
| Continued statements
should use double indentation |
Statements that span more than one line should use a
double indentation on the second and subsequent lines. An example of double indentation
is:
if ( 0 == gameOver
&& YOU == playerToMove )
printf( "Your move\n" );
|
|
| Avoid nesting indentation
more than five |
The body of compound statements (if statements and loop
structures, etc.) should not be nested to a total depth of more than five. |
Blank Lines
Blank lines can be used to delineate sections of code. There are several rules that
should be used which include:
| Follow variable
declarations with at least one blank line |
Put one or two blank lines after the list of variable
declarations within a function before the code. |
| Divide your code into
logical paragraphs with delineating blank lines |
Divide your code in functions into logical paragraphs. |
| Blank line before comment |
Put a blank line before comments unless the preceding
line contains only an open brace ("{"). |
| Surround struct, union and
class declarations with blank lines |
Put a blank line before and after struct, or union, or
class declarations. The only exception should be when there is a comment immediately
preceding the declaration (which there should be). |
| Separate function definitions
with at least two blank lines |
Separate function definitions with at least two blank
lines. |
Spaces
In addition to the spaces used for indentation, spaces may be used to isolate arguments
and expression components.
| Follow language
keywords with a space |
'C' keywords (e.g., if, while, for, ...) should be
followed by at least a single space. The only exception is the sizeof() operator which
follows the same rules as a function. |
| Separate function
arguments with spaces |
Function arguments should have at least one space
following the comma. The arguments should also be separated from the parenthesis with a
space. |
| Surround binary operators
with spaces (Exceptions: structure/class member operators (".",
"->", "::")) |
To clearly delineate binary operators from the rest of
the expression they should be surrounded by spaces. The exceptions are the ("."
and "->") structure member operators along with the ("::")
class member operator, which should not be surrounded with spaces. |
| Do NOT use spaces to
delineate unary operators |
Avoid putting spaces between unary operators and their
single operand. |
| Surround the logical binary
operators with double spaces |
To clearly delineate the logical binary operators
("&&", "||") from the rest of the expression
they should be surrounded by double spaces |
| Separate for-loop expressions
with spaces |
For-loop expressions should have at least one space
following the semicolon. The expressions should also be separated from the parenthesis
with a space |
| Line up variables in
declarations |
Use spaces or tabs to line up variables in lists of
declarations. |
Code Blocks
Align braces with the control statement
|
Blocks of code in C/C++ are delimited by braces
("{" and "}"). The braces should be aligned with the control statement
and NOT the indented statements.
control_statement
{
statements;
}
|
|
Put braces on a line by themselves
(exception: "while" of "do/while" loop & tag-name for a
structure typedef) |
The braces should not be placed on the same line
with the control statement. The only exception is the "while" of a do/while loop
and the tag name for a typedef.
struct name
{
declarations;
};
typedef struct TagName
{
declarations;
} TagName; rule exception
if ( condition )
{
statements;
}
while ( condition )
{
statements;
}
do
{
statements;
} while ( condition ); rule exception
switch ( expression )
{
case labela :
case labelb :
...
break;
case labelc :
...
break;
default :
...
break;
}
|
|
| Use braces for multiply
nested statements |
It is a good practice to use braces to delimit code for
the iteration and branch constructs whenever there is the slightest chance that code
clarity is improved. A general rule is if the iteration or branch construct contains more
than a single statement then enclose them in braces. For example:
if ( condition )
while ( some condition )
if ( another condition )
statement;
|
Even though the nested construct above is legal it is definitely clearer and less
ambiguous when written using braces.
if ( condition )
{
while ( some condition )
{
if ( another condition )
statement;
}
}
|
|
| Use braces for all blocks
of an if/else-if chain when one block requires braces |
It is very often desirable to use braces on all blocks
of an if/else-if chain whenever one or more if statements require braces in the chain. As
an example:
if ( condition )
statement;
else if ( some condition )
{
statement-2;
statement-3;
}
|
Instead use:
if ( condition )
{
statement;
}
else if ( some condition )
{
statement-2;
statement-3;
}
|
|
Statements
| Non-Multiple Statement
Lines |
Each line of source code should contain, at most, a
single executable statement. Statements may however be continued on multiple lines. For
this purpose the controlling portion of a loop or branch is considered to be a separate
statement. Good Statements
statement;
|
single statement |
state
ment;
|
simple continued statement |
label:
statement;
|
label on line by itself |
if ( condition )
statement;
|
if on separate line |
Bad Statements
statement1; statement2;
|
more than one statement |
if ( condition ) statement;
|
statement on line with if |
case label: statement;
|
statement on line with label |
|
| Comment empty
statements |
There are times when you need to have an empty
statement, such as some loops where the real work is done in the loop construct. Its also
a good idea to have the empty statement on a line by itself.
while ( *pDest++ = *pSrc++ )
; // empty
|
|
Continued Statements
| Always break long
expressions at operators |
Attempt to break the expression based on operator
precedence. In general try to start the continued line with the operator. There are times
when an expression should be broken onto more than the minimum number of lines so that
each line contains a clear lexical portion of the expression.
if ( 0 == gameOver
&& YOU == playerToMove )
printf( "Your move\n" );
|
|
| Don't be afraid to begin the
continued line with the assignment operator |
someLongVariableOrExpression
= someExpression * thatIsContinued;
|
|
| Examples of specific
continued statement situations |
When the ternary question operator (?:) is continued it
should be divided something like:
c = ( a == b )
? d + f( a )
: f( b ) - d;
|
One other note about continued lines is the way a for loop should be continued. If any
of the 'for' control structures need to be continued, then each should be placed on a line
by itself.
for ( initialization;
condition;
increment )
statement;
|
When continuing a function call the continued lines should line up with the open
parenthesis (or at least the nearest indentation).
result = package_someFunc( argumentOne, argumentTwo,
argumentThree, argFour,
argumentFive );
|
Or if the function name is long enough (when accompanied by the preceding
expression(s)) to prevent the first argument from being included on the same line as the
function name, then double indent past the beginning of the function name to place the
open parenthesis and align the arguments with the open parenthesis.
someRealLongName = somePackage_someFunctionWithLongName
(
argumentOne, argumentTwo,
argumentThree,
argumentFour, argumentFive
);
|
|