Global variables are highly undesirable. Even static variables within
a file are undesirable, especially when used to avoid passing parameters.
With as few exceptions as possible, all variables accessed by a function
should be parameters to it or locals. This allows people reading the
code to be able to understand a function without looking outside the
function code itself.
Also it allows a function to be relocated to another file without relying
on static variables within the original file.
An example of a valid use of global variables would be as run-time constants, i.e., values which might be initialized at the beginning of the program, and then accessed in a read-only manner.
Continuation lines of functions should line up with the '(', if
reasonable:
x = find_shortest_path( p1, p2, p3,
parameter4,
parameter5 );
Exception: (if no room)
{
x = find_shortest_path(
parameter1,
parameter2,
parameter3,
parameter4,
parameter5,
parameter6 );
}
In most cases, you should use a defined constant instead of a numerical
constant, as a documentation aid:
WRONG:
index = day / 7;
RIGHT:
index = day / NUMBER_DAYS_IN_WEEK;
Exceptions to this rule occur where it is clearer and easier to maintain correctness by using an explicit numerical constant:
avg = (p1 + p2 + p3 + p4) / 4;
while( function() );
because someone might someday add code for the body of the loop,
and forget to take out the semicolon:
while( function() );
{
body();
}
The above is valid C code, but does not do what is required. Use:
while( function() )
{
}
For structures that are 8 bytes or more, it is much more efficient to
pass by reference, rather than value, for most compilers.
public void function( parameter )
image_struct *parameter;
{
}
Full-line comments should be at the same
indentation level as the
code, with a blank line above and below.
Same-line comments should be
separated from the code by many spaces:
n = 10;
/* find the largest value in the array */
max = a[0];
for( i = 1; i < n; ++i )
{
if( a[i] > max )
{
max = a[i]; /* new max */
}
}
c = max; /* initialize counter */
Use enumerated types for variables with a limited number of values.
WRONG:
#define MR_FORMAT 1
#define PET_FORMAT 2
#define IFF_FORMAT 3
#define FREE_FORMAT 4
main()
{
int input_format;
input_format = MR_FORMAT;
}
RIGHT:
typedef enum {
MR_FORMAT,
PET_FORMAT,
IFF_FORMAT,
FREE_FORMAT
} file_format_types;
main()
{
file_format_types input_format;
input_format = MR_FORMAT;
}
Use explicit type-casting whenever conversion between types is to
be done:
{
int int_x;
float float_x;
float_x = 3.56;
int_x = (int) float_x;
}
{
voxel_struct *current_voxel;
if( current_voxel == (voxel_struct *) 0 )
{
exit( 1 );
}
}
Never treat integers like booleans (flags). Never treat booleans like
integers:
WRONG:
{
int invert_flag;
int number_of_slices;
if( number_of_slices )
{
}
if( invert_flag == 0 )
{
}
}
RIGHT
{
int invert_flag;
int number_of_slices;
if( number_of_slices != 0 )
{
}
if( !invert_flag )
{
}
}
One possible exception is:
/* returns 0 or an error */
if( input_file( file, data ) )
{
(void) print( "Error\n" );
}