||Declarations and Definitions
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
||Generally names and identifiers should be less than 33
characters long. They must be unique within 31 characters.
|Avoid names that differ only
||Names that differ only by case should be strictly
avoided. This especially true of public/global names.
|Avoid names that look like
||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
|Avoid underscores in typedef
||Underscore characters should be strictly avoided when
creating new typedef 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
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.
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.
||string (char* or char )
||string - zero terminated (synonym for 's')
||string - counted (first byte contains character count)
||int or long-int
||word (unsigned short)
||real (probably double)
|Boolean (true or false)
||boolean (true or false)
||tag (typedef or struct)
|Other general prefixes
||handle (pointer to pointer)
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'.
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
||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.
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
Non-Hardware Dependent Declarations
Even if code is destined for only one machine, the data sizes should not be assumed.
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
||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.
|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
|Avoid assumptions concerning
||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
||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
||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; /* file version (string) */
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.
|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.
( // 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: