Views
C Style Guide
Introduction
The style and layout to be used for programming on cmgui, cmulgeom, gx, mulgraph, emap and related projects.
For the examples in this document, < and > are used to enclose things that depend on the instance.
For questions, clarification or justification see David Bullivant.
Layout
General
- Tabs are used for indentation.
- A tab is 2 spaces.
- Tabs are only used for indentation (can only appear at the beginning of a line).
- The line length is 80 characters (with tabs counting as 2 spaces).
- If a statement extends over more than one line then the extension lines are indented one tab from the first line (includes comments).
- For a compound statement, the { and } are on
separate lines and have the same level of indentation as the statment it is
a condition of. The body of the compound statement should be indented by 1
tab, e.g.,
if (<condition>)
{
<body>
} - There should be no trailing spaces or tabs.
- #ifdef and #ifndef are not used. #if defined (<MACRO>) and #if !defined (MACRO) are used instead.
- No spaces after ,'s or around operators, except *=, /=, +=, -=, %=, <<=, >>=, &=, = and |=.
- The spacing in the examples in this guide is deliberate and part of the layout.
- MACRO names should be in upper case.
Module
In general, a module is built around a data structure or group of data structures and contains the type definitions (.h) and the function prototypes (.h) and function definitions (.c) for manipulating the types. For a widget module, there may also be a .uil file.
Notes:
- Module names are in lower case (use _ for separating words).
.h File
/*******************************************************************************
FILE : <module_name>.h
LAST MODIFIED : <day> <month as name> <year including century>
DESCRIPTION :
<A description of what the module is for and what it can do.>
==============================================================================*/
#if !defined (<module name in capitals>_H)
#define <module name in capitals>_H
#include <<system includes>>
#include "<project includes specified relative to project base directory eg.
graphics/finite_element.h>"
/*
Global types
------------
*/
<type definitions>
/*
Global variables
----------------
*/
<variable declarations. Should all be storage class extern>
/*
Global functions
----------------
*/
<prototypes for the functions that can be used by other modules>
#endif
Notes:
- The section comments should be as shown.
- The spacing between sections should be as shown.
- The ordering of the sections should be as shown.
.c File
/*******************************************************************************
FILE : <module_name>.c
LAST MODIFIED : <day> <month as name> <year including century>
DESCRIPTION :
<A description of what the module is for and what it can do.>
==============================================================================*/
#include <<system includes>>
#include "<project includes specified relative to project base directory eg.
graphics/finite_element.h>
/*
Global variables
----------------
*/
<variable declarations. Same as in .h except without extern and with
initializers>
/*
Module types
------------
*/
<declarations for types which are only used within the module. Should be
storage class static>
/*
Module variables
----------------
*/
<declarations for variables which are global to this module only. Should be
storage class static>
/*
Module functions
----------------
*/
<definitions for functions which are used in this module only. Should be
storage class static>
/*
Global functions
----------------
*/
<definitions for the functions prototyped in .h>
Notes:
- The section comments should be as shown.
- The spacing between sections should be as shown.
- The ordering of the sections should be as shown.
.uil File
!*******************************************************************************
!FILE : <module_name>.uil
!
!LAST MODIFIED : <day> <month as name> <year including century>
!
!DESCRIPTION :
!<A description of what the widgets are for.>
!===============================================================================
module <module_name>_module
names=case_sensitive
procedure
<names of the procedures used in the uil code and assigned in the C code. On
separate lines>
identifier
<names of the identifiers used in the uil code and assigned in the C code. On
separate lines>
object
<the widget definitions>
end module;
Notes:
- The spacing between sections should be as shown.
- The ordering of the sections should be as shown.
struct Declaration
Top Level
struct <Struct_name>
/*******************************************************************************
LAST MODIFIED : <day> <month as name> <year including century>
DESCRIPTION :
<A description of what the type is for.>
==============================================================================*/
{
<struct body>
}; /* struct <Struct_name> */
Notes:
- First letter of the structure name is upper case.
As a Field
struct
{
<struct body>
} <field_name>;
Notes:
- First letter of the structure name is lower case.
union Declaration
As for struct, but with struct replaced by union.
enum Declaration
enum <Enum_type>
/*******************************************************************************
LAST MODIFIED : <day> <month as name> <year including century>
DESCRIPTION :
<A description of what the type is for.>
==============================================================================*/
{
<ENUM_CONSTANTs on separate lines>
}; /* enum <Enum_type> */
Notes:
- First letter of the structure name is upper case.
- Constants are in upper case.
Function Prototype
<return type> <function_name>(<parameter list>);
/*******************************************************************************
LAST MODIFIED : <day> <month as name> <year including century>
DESCRIPTION :
<A description of what the function does and what the parameters are.>
==============================================================================*/
Notes:
- Should be the same (including the comment) as the function header in the .c files apart from the added ;.
Function Definition
<return type> <function_name>(<parameter list>)
/*******************************************************************************
LAST MODIFIED : <day> <month as name> <year including century>
DESCRIPTION :
<A description of what the function does and what the parameters are.>
==============================================================================*/
{
<variable declarations>
ENTER(function_name);
<function body>
LEAVE;
return (<return_variable>);
} /* <function_name> */
Notes:
- Should be the same (including the comment) as the function header in the .h files apart from the added ; in the .h file.
- Notice the use of the ENTER and LEAVE macros.
Variable Declarations
int anatomical_list_length,coordinate_list_length,field_list_length,i;
struct FE_node_field *node_field_1,*node_field_2;
struct FE_node_field_component *component_1,*component_2;
struct FE_node_field_info *field_info;
struct FE_node_field_info_list_item *item;
struct FE_node_field_list_item *node_field_item;
if Statement
if (<condition>)
{
<then clause>
}
else
{
<else clause>
}
Notes:
- The { and } are always present, even if there is only one statement in the clause.
- The else clause is optional.
do Statement
do
{
<do body>
} while (<condition>);
Notes:
- The { and } are always present, even if there is only one statement in the clause.
while Statement
while (<condition>)
{
<while body>
}
Notes:
- If there are one or more statements in the body then the { and } should be used. If there are no statements in the body then while (<condition>); should be used.
for Statement
for (<initialize>;<terminate>;<update>)
{
<for body>
}
Notes:
- The { and } are always present, even if there is only one statement in the clause.
switch Statement
switch (<expression>)
{
case <case_label1>: case <case_label2>:
{
<case clause>
} break;
default:
{
<default clause>
} break;
}
Notes:
- The { and } are always present, even if there is only one statement in the clause.
- The breaks should always be used.
Debug Statements
Debug statements should be preceded by the comment
/*???debug */and the indentation should be restarted in column 1.
Comments
Apart from the special comments shown above, all comments should be on separate lines and be indented at the current level of indentation. Temporary comments querying existing code or suggesting enhancements should be of the form
/*???<programmer identification> . <text> */
Style
return
The return statement should only ever be the last statement in a function. There should be at most one return statement per function.
exit
The exit statement should not be used.
break
The break statement should only be used to end clauses in a switch statement (see above).
continue
The continue statement should not be used.
goto
goto should not be used.
elseif
elseif should not be used.
typedef
typedef should not be used for struct's, union's or enum's.
Memory Allocation
The macros ALLOCATE and DEALLOCATE (in general/debug.h) should be used for all memory allocation and deallocation (no malloc or free).
ENTER and LEAVE (in general/debug.h)
ENTER should be the first statement and LEAVE should be the second to last or last (if no return) statement in every function.
Comments
Comments should be factual, and should only attempt humour if they are bloody funny.
Clarity
Code should not be obscure. One tactic to help achieve this is to only do one thing per statement, e.g.,
a[i]=b;instead of
i++;
a[i++]=b;
Lists
Macros have been written (graphics/list.h) for creating and using lists. These macros should be used for all lists.
Casting NULL
NULL should always be caste to the appropriate type.
Using reference counting
Reference counting should be carried out using the macros ACCESS, DEACCESS, and REACCESS on objects that need it. When this is done, the following rules apply:
- Before storing a pointer into a structure, ACCESS the pointer.
- DEACCESS when nulling out a pointer.
- Set the access count to zero in CREATE. ACCESS is then required after CREATE.