Coding Guidelines
Generic Guidelines
Declarations and Definitions
<- ^ ->
<< ^^ >>


Naming

The names that are used for constants, variables, functions, etc. are critically important to good maintainable code. Names should always be descriptive. Avoid using terse and non-obvious names. Conversely don't be overly verbose with your names. Public names are the most critical since other programmers are likely to use them.

General naming guidelines

Use descriptive names Make identifier names descriptive of their contents. Avoid terse names that have little or no meaning.
Limit names to 32 characters Generally names and identifiers should be less than 33 characters long. They must be unique within 31 characters.
Avoid names that differ only in case Names that differ only by case should be strictly avoided. This especially true of public/global names.
Avoid names that look like each other Names that are ambiguous to the human reader should be strictly avoided. For instance: "l" (lower-case L) and "1" (numeric digit one) can be easily confused or "O" (upper-case letter O) and "0" (numeric digit zero). Similarly, avoid differences like "foobar" and "foo_bar", the potential for confusion is considerable.

Structure, typedef and class names

Begin typedef names with a capital letter The typedef name should always begin with a capital letter. Typically, if a typedef's name includes more than one word, each word is capitalized and concatenated.
typedef struct StringCounted  StringCounted;
Use the same name for the structure tag and the typedef name If a structure tag name is used it should be identical to the typedef name. Another consideration is that the typedef name should be such that collision with a typedef that is in a system include file on any of the (many) systems we support is unlikely. For this reason, avoid a typedef name like Rect. A better name would be DeptRectangle ("Dept" indicating a department abbreviation) or something else that is unlikely to collide. There are some cases where this guideline has not been followed in the past, and eventually it is going to cause us problems. Let's make sure we do not create any more.
typedef struct Point2d
{
    long    x;
    long    y;
} Point2d;
Avoid underscores in typedef names Underscore characters should be strictly avoided when creating new typedef names.

Variable Names

Begin variable and parameter names with a lowercase letter There are two forms of variables in 'C', local (or private) and global (or public). Both should always begin with a lowercase letter. Each subsequent "word" in the name should be capitalized and concatenated to the previous word. It is important to use variable names that have clear and non-ambiguous meanings.

In general functions should be kept relatively small, so the need for long descriptive local variable names is limited. The important consideration is that all functions within a file should have consistency between them.

Simplified Hungarian notation for variable names Some Companies, most notably Microsoft, have standardized on the Hungarian Notation. In Hungarian Notation, variables are to be prefixed with lowercase tags followed by the variable name "words" each beginning with a capital letter.

An example:

double* pdLength; 

Which indicates pointer to double. In most cases there will be a single or double character prefix. The complete Hungarian Notation is highly complex, however the following is a simplified form of the prefixes and their corresponding meanings.

Characters
c char
s string (char* or char [])
sz string - zero terminated (synonym for 's')
sc string - counted (first byte contains character count)
sw wide-character string
Integers
i int
n int or long-int
u unsigned
w word (unsigned short)
Floating point
f float
d double
r real (probably double)
Enumerations
e enum
Boolean (true or false)
b boolean (true or false)
Structures (typedef)
t tag (typedef or struct)
Other general prefixes
a array
p pointer
h handle (pointer to pointer)
k constant
g global variable

Public (Global) Variable Names

Prefix global variable names with "g" It is important that public variables be descriptive enough that collision with variables or functions in the name space of one of the (many) systems our products run on do not occur. For example a public variable called 'error' is a poor idea, since it is almost sure to conflict on some system. A possible solution is to precede the name with an indication that it is global, for example a lower case 'g'.

There are several special considerations that need to be observed when dealing with variables that have public scope. Please remember that non-static variables defined outside of a function are public names.

Don't count on capitalization to differentiate names Don't count on case sensitivity to make ANY public names (functions or global variables) unique. Some systems or development environments convert all public names to a single case for the link process.
Limit the number of global variables Some machines or linkers have a limited number of global variables. If you must use global variables, cluster the variables into logical structures and then define the structures global.

Declarations

Public declarations should be kept to the absolute minimum required. If the function is only referenced from within the source file, define it as static. When creating a new function, the natural tendency should be to make it static. Since the scope for static functions and variables is limited to the source file that defined them, if one is changed, it is not necessary to search outside of the current source file to resolve references.

Non-Hardware Dependent Declarations

Even if code is destined for only one machine, the data sizes should not be assumed.

The 'int' data type should be treated as a 'short' data type int is defined to be the natural size of an integer on the hardware. Since an int on some systems is the size of a short an int should always be assumed to be no larger than a short. Another way to think about it is that an int should never hold more data than a short but may occupy the memory of a long.
Never assume the sizes of data types You should never depend on the size of types int, double or pointers. Some programmers assume that an int and a long and a pointer are all the same size. Or that a double is always going to be 8 bytes. These are bad and dangerous assumptions, especially as they relate to structures.
type 80x86 680x0 Clipper Cray-2 Unisys 1100
char 8 8 8 8 9
short 16 16 16 64(32) 18
int 16/32 16/32 32 64(32) 36
long 32 32 32 64 36
char* 16/32/48 32 32 64 72
int* 16/32/48 32 32 64(24) 72
int (*)() 16/32/48 32 32 64 72
Use typedefs to create predictable data sizes If a predictable datum size is needed then a typedef should be declared and used for definitions. This will allow the typedef to be conditionally declared based on machine/system sizes.
Be careful about the range and precision for floating point It is dangerous to assume that when a floating point value allocates a given number of bits that the range or precision are always completely allocated.
Avoid assumptions concerning memory alignment Some machines require data types to be aligned in memory based on their elemental sizes. This can cause unused holes in memory. This is especially obvious when dealing with heterogeneous structures.
Avoid assumptions concerning memory order Some machines organize memory such that bytes of a word are of increasing significance with increasing address (little-endian), or of decreasing significance with increasing address (big-endian).

Global Variable Declarations

Limit the number of global variables Global variables should be avoided when possible. However, if global variables are necessary, pack them inside of a structure and only declare that structure as a global. This also helps avoid collision with system names (which otherwise is quite possible in this example):
extern int  fmode;      /* file modes */
extern char version[];  /* file version number */

instead try using:

typedef struct FileProperties
{
    int     fmode;       /* file modes */
    char    version[20]; /* file version (string) */
} FileProperties;

extern FileProperties* gpFileProperties; 

The second construct illustrates another factor that should be considered when using global variables. Some of the platforms that we develop on have a fixed and limited amount of static variable space. If the technique of packing "global" variables in a single structure is used, then the structure can be malloc'ed instead of allocating it statically and accessed via a pointer.

Function Declarations

Declare all public functions in header files All functions that are not explicitly declared as static should be declared in a header file.
Declare each function argument on individual lines ANSI declarations are used for all functions. Each argument should be listed on a separate line. Each argument should be accompanied by a comment that identifies whether the argument is input (IN), output (OUT), or updated (I/O) and an explanation of how it is used. The argument names should be lined up vertically.
int     somePackage_someFunction
        (                  // RTN: status of operation
        Rect*      pRect,  // OUT: enclosing rectangle
        MSWindow*  pMsWin, // IN: "moused" window
        IconMenu*  pIcm,   // IN: "moused" icon cmd menu
        Handle     hItem   // IN: handle to item
        );

Functions that have no arguments should be declared like:

void    somePackage_functionWithNoArgs
        (
        void
        );

<- ^ ->
<< ^^ >>
Last modified: 25 May 2009
copyright 2004 Bear Consulting Group