C_coding_standards_04_09
C_coding_standards_04_09
Version 0.2
Date Tuesday, Apr 14, 2009
The information contained herein is CONFIDENTIAL proprietary to NESPL, and may not be
used, reproduced, or disclosed to others except as specifically authorised by NESPL. The
recipient of this information, by its retention and use agrees to protect this document and the
information contained herein from loss, theft or compromise. You may not discuss the
contents of this document to any third parties without the consent of NESPL.
©NESPL Confidential Coding Standards - C
DOCUMENT AUTHORISATION
AUTHOR
_____________________________ __________________
Person Date
Title
APPROVAL
_____________________________ __________________
Person Date
Title
_____________________________ __________________
Person Date
Title
CUSTOMER
_____________________________ __________________
Person Date
Title
_____________________________ __________________
Person Date
Title
ACCEPTANCE
_____________________________ __________________
Person Date
Title
TABLE OF CONTENTS
1 Introduction...........................................................................................................................................7
2 File Organization ..................................................................................................................................7
2.1 File Naming Conventions..........................................................................................................7
2.2 Program Files............................................................................................................................7
2.3 Header Files..............................................................................................................................8
2.4 Other Files.................................................................................................................................8
3 Comments ............................................................................................................................................8
4 Declarations..........................................................................................................................................9
5 Examples ............................................................................................................................................11
6 Simple Statements .............................................................................................................................11
7 Compound Statements.......................................................................................................................12
8 Operators............................................................................................................................................14
9 Naming Conventions ..........................................................................................................................14
10 Constants .........................................................................................................................................14
11 Macros ..............................................................................................................................................15
12 Conditional Compilation. ..................................................................................................................15
13 Debugging ........................................................................................................................................15
14 Portability..........................................................................................................................................16
15 ANSI C..............................................................................................................................................17
15.1 Compatibility ........................................................................................................................17
15.2 Formatting ...........................................................................................................................17
15.3 Prototypes ...........................................................................................................................17
15.4 Pragmas ..............................................................................................................................17
16 Special Considerations.....................................................................................................................18
17 Lint ....................................................................................................................................................18
18 Make.................................................................................................................................................19
19 Project-Dependent Standards ..........................................................................................................20
20 Conclusion........................................................................................................................................21
LIST OF FIGURES
LIST OF TABLES
GLOSSARY
Term Explanation
1 Introduction
The scope of this work is C coding style. This document tries to combine work on C style into a
uniform set of standards that should be appropriate for any project using C.
The standards in this document must be adopted as a part of program acceptance to increase
portability, reduce maintenance, and above all improve clarity.
2 File Organization
A file consists of various sections that should be separated by several blank lines. The editor may
not have enough temp space to edit the file, compilations will go more slowly, etc.
The first character of the name should be a letter and all characters (except the period) should be
lower-case letters and numbers. The base name should be eight or fewer characters and the
suffix should be three or fewer characters (four, if you include the period). These rules apply to
both program files and default files used and produced by the program.
C++ has compiler-dependent suffix conventions, including .c, , .cc and .C. Since much C code is
also C++ code, there is no clear solution here.
Example – sndcpMessageHandler.c,
sndcpMain.c
sndcpIE.h
Example – 3g_release6/umts_ms/rrc/src/
3g_release8/umts_ms/rrc/inc/
3g_release5/umts_ms/release/rrc*
3g_release5/umts_stub/release/rrcStub
3g/umts_ms/obj/
NOTE:-
1. All header files should be kept in src directory
2. All source files should be kept in inc directory
1. The prologue may optionally contain author(s), revision control information, references,
etc.
2. Any system header file includes should be before user include files.
3. To add any defines and typedefs that apply to the file the order is to have "constant"
macros first, then "function" macros, then typedefs and enums.
4. The global (external) data declarations, should be in the order: externs, non-static
globals, static globals.
5. Lastly, functions should be in some sort of meaningful order. Like functions should
appear together. If defining large numbers of essentially-independent utility functions,
consider alphabetical order.
• Header files should be functionally organized, i.e., declarations for separate subsystems
should be in separate header files. Also, if a set of declarations is likely to change when
code is ported from one machine to another, those declarations should be in a separate
header file.
• Avoid private header filenames that are the same as library header filenames.
• Header files that declare functions or external variables should be included in the file that
defines the function or variable.
• Header files should not be nested. The prologue for a header file should, therefore,
describe what other headers need to be #included for the header to be functional. In
extreme cases, where a large number of header files are to be included in several
different source files, it is acceptable to put all common #includes in one include file.
• It is common to put the following into each .h file to prevent accidental double-inclusion.
#ifndef EXAMPLE_H
#define EXAMPLE_H
... /* body of example.h file */
#endif /* EXAMPLE_H */
Have a file called "README" to document both "the bigger picture" and issues for the program as
a whole.
3 Comments
• Avoid, however, comments that are clear from the code, as such information rapidly gets
out of date.
• Comments should be short and to the point.
• Comments should justify offensive code. The justification should be that something bad
will happen if unoffensive code is used.
• The comment should explain the unacceptable behavior and describe why the hack is a
"good" fix.
• Comments that describe data structures, algorithms, etc., should be in block comment
form with the opening /* in columns 1-2, a * in column 2 before each line of comment text,
and the closing */ in columns 2-3. An alternative is to have ** in columns 1-2, and put the
closing */ also in 1-2.
/*
* Here is a block comment.
* The comment text should be tabbed or spaced over uniformly.
* The opening slash-star and closing star-slash are alone on a
line.
*/
/*
** Alternate format for block comments */
if (argc > 1)
{
/* Get input file from command line. */
if (NULL == freopen(argv[1], "r", stdin))
{
Perror (argv[1]);
}
}
• Very short comments may appear on the same line as the code they describe, and
should be tabbed over to separate them from the statements.
if (a == EXCEPTION)
{
b = TRUE; /* special case */
}
else
{
b = isprime(a); /* works only for odd a */
}
4 Declarations
char* s,
char* t,
char* u;
instead of
which is wrong, since 't' and 'u' do not get declared as pointers.
• Any variable whose initial value is important should be explicitly initialized, or at the very
least should be commented to indicate that C's default initialization to zero is being relied
upon. The empty initializer, "{}", should never be used.
• Structure initializations should be fully parenthesized with braces. Constants used to
initialize longs should be explicitly long. Use capital letters.
• In any file which is part of a larger whole rather than a self-contained program, maximum
use should be made of the static keyword to make functions and variables local to single
files.
• Variables in particular should be accessible from other files only when there is a clear
need that cannot be filled in another way. Such usage should be commented to make it
clear that another file's variables are being used; the comment should name the other
file. If your debugger hides static objects you need to see during debugging, declare them
as STATIC and #define STATIC as needed.
• The most important types should be highlighted by typedeffing them.
• The return type of functions should always be declared. If function prototypes are
available, use them.
• Each function should be preceded by a block comment prologue that gives a short
description of what the function does and (if not clear) how to use it. Discussion of non-
trivial design decisions and side-effects is also appropriate. Avoid duplicating information
clear from the code.
• Comments for parameters and local variables should be tabbed so that they line up
underneath each other. Local variable declarations should be separated from the
function's statements by a blank line.
• If the function uses any external variables (or functions) that are not declared globally in
the file, these should have their own declarations in the function body using the extern
keyword.
• Avoid local declarations that override declarations at higher levels. In particular, local
variables should not be redeclared in nested blocks. Whitespace.
• Use vertical and horizontal whitespace generously. Indentation and spacing should
reflect the block structure of the code; e.g., there should be at least 2 blank lines between
• Other complex expressions, particularly those using the ternary ?: operator, are best split
on to several lines, too.
c = (a == b)
? d + f(a)
: f(b) - d;
• Keywords that are followed by expressions in parentheses should be separated from the
left parenthesis by a blank. (The sizeof operator is an exception.) Blanks should also
appear after commas in argument lists to help separate the arguments visually. On the
other hand, macro definitions with arguments must not have a blank between the name
and the left parenthesis, otherwise the C preprocessor will not recognize the argument
list.
5 Examples
/*
* Determine if the sky is blue by checking that it isn't night.
* CAVEAT: Only sometimes right. May return TRUE when the
answer
* is FALSE. Consider clouds, eclipses, short days.
* NOTE: Uses 'hour' from 'hightime.c'. Returns 'int' for
* compatibility with the old version.
*/
int /* true or false */
skyblue()
{
extern int hour; /* current hour of the day
*/
/*
* Find the last element in the linked list
* pointed to by nodep and return a pointer to it.
* Return NULL if there is no last element.
*/
node_t *
tail(nodep)
node_t *nodep; /* pointer to head of list
*/
{
register node_t *np; /* advances to NULL */
register node_t *lp; /* follows one behind np
*/
if (nodep == NULL)
return (NULL);
for (np = lp = nodep; np != NULL; lp = np, np = np-
>next)
; /* VOID */
return (lp);
}
6 Simple Statements
There should be only one statement per line unless the statements are very closely related.
even though FAIL may have the value 0 which C considers to be false. An explicit test will help
you out later when somebody decides that a failure return should be -1 instead of 0.
Explicit comparison should be used even if the comparison value will never change.It is common
practice to declare a boolean type "bool" in a global include file. The special names improve
readability immensely.
typedef int bool;
#define FALSE 0
#define TRUE 1
or
typedef enum
{
NO=0,
YES
bool;
Even with these declarations, do not check a boolean value for equality with 1 (TRUE, YES, etc.);
instead test for inequality with 0 (FALSE, NO, etc.). Most functions are guaranteed to return 0 if
false, but only non-zero if true. Thus,
if (TRUE == func()) { ...
must be written
if (FALSE != func()) { ...
Rename the function/variable or rewrite the expression so that the meaning is obvious without a
comparison to true or false (e.g., rename to isvalid()).
7 Compound Statements
When a block of code has several labels (unless there are a lot of them), the labels are placed on
separate lines. The fall-through feature of the C switch statement, must be commented for future
maintenance. A lint-style comment/directive is best.
switch (expr)
{
case ABC:
case DEF:
statement;
break;
case UVW:
statement;
/*FALLTHROUGH*/
case XYZ:
statement;
break;
default:
break;
}
Here, the last break is unnecessary, but is required because it prevents a fall-through error if
another case is added later after the last one. The default case, if used, should be last and
does not require a break if it is last.
Whenever an if-else statement has a compound statement for either the if or else section, the
statements of both the if and else sections should both be enclosed in braces (called fully
bracketed syntax).
if (expr)
{
statement;
}
else
{
statement;
statement;
}
Braces are also essential in if-if-else sequences with no second else such as the following, which
will be parsed incorrectly if the brace after (ex1) and its mate are omitted:
if (ex1)
{
if (ex2)
{
funca();
}
}
else
{
funcb();
}
An if-else with else if should be written with the else conditions left-justified.
The format then looks like a generalized switch statement and the tabbing reflects the switch
between exactly one of several alternatives rather than a nesting of statements.
8 Operators
Unary operators should not be separated from their single operand. Generally, all binary
operators except '.' and '->' should be separated from their operands by blanks. Some judgement
is called for in the case of complex expressions, which may be clearer if the "inner" operators are
not surrounded by spaces and the "outer" ones are.
If you think an expression will be hard to read, consider breaking it across lines. Splitting at the
lowest-precedence operator near the break is best. Since C has some unexpected precedence
rules, expressions involving mixed operators should be parenthesized.
The binary comma operator should be avoided. The comma operator is most useful to provide
multiple initializations or operations, as in for statements.
Complex expressions, for instance those with nested ternary?: operators, can be confusing and
should be avoided if possible.
The logical expression operand before the?: should be parenthesized and both return values
must be the same type.
9 Naming Conventions
• Names with leading and trailing underscores are reserved for system purposes and
should not be used for any user-created names.
• #define constants should be in all CAPS.
• Enum constants are Capitalized or in all CAPS
• Function, typedef, and variable names, as well as struct, union, and enum tag names
should be in lower case.
• Many macro "functions" are in all CAPS. Lower-case macro names are only acceptable if
the macros behave like a function call.
• Avoid names that differ only in case, like foo and Foo. Similarly, avoid foobar and
foo_bar. The potential for confusion is considerable.
• Similarly, avoid names that look like each other.
• In general, global names (including enums) should have a common prefix identifying the
module that they belong with. Globals may alternatively be grouped in a global structure.
Typedeffed names often have "_t" appended to their name.
• Avoid names that might conflict with various standard library names. Some systems will
include more library code than you want. Also, your program may be extended someday.
10 Constants
Numerical constants should not be coded directly. The #define feature of the C preprocessor
should be used to give constants meaningful names. Constants should be defined consistently
with their use.
Simple character constants should be defined as character literals rather than numbers. Non-text
characters are discouraged as non-portable. If non-text characters are necessary, particularly if
they are used in strings, they should be written using a escape character of three octal digits
rather than one.
11 Macros
The macro should be used in implementing the function so that changes to the macro will be
automatically reflected in the function.
Macros should avoid using globals, since the global name may be hidden by a local declaration.
Macros that change named parameters (rather than the storage they point at) or may be used as
the left-hand side of an assignment should mention this in their comments.
Macros that take no parameters but reference variables, are long, or are aliases for function calls
should be given an empty parameter list.
Except for type casts, sizeof, and hacks such as the above, macros should contain keywords only
if the entire macro is surrounded by braces.
12 Conditional Compilation.
If you #ifdef machine dependencies, make sure that when no machine is specified, the result is
an error, not a default machine. Use "#error" and indent it so it works with older compilers. If you
#ifdef optimizations, the default should be the unoptimized code rather than an uncompilable
program. Be sure to test the unoptimized code.
Put #ifdefs in header files instead of source files when possible. Use the #ifdefs to define macros
that can be used uniformly in the code.
13 Debugging
If you use enums, the first enum constant should have a non-zero value, or the first constant
should indicate an error.
Check for error return values, even from functions that "can't" fail. Consider that close() and
fclose() can and do fail, even when all prior file operations have succeeded. Write your own
functions so that they test for errors and return error values or abort the program in a well-defined
way. Include a lot of debugging and error-checking code and leave most of it in the finished
product. Check even for "impossible" errors.
Use the assert facility to insist that each function is being passed well-defined values, and that
intermediate results are well-formed.
14 Portability
This section gives some guidelines for writing portable code. The following is a list of pitfalls to be
avoided and recommendations to be considered when designing portable code:
• Write portable code first, worry about detail optimizations only on machines where they
prove necessary. Document performance hacks and localize them as much as possible.
• Recognize that some things are inherently non-portable.
• Organize source files so that the machine-independent code and the machine-dependent
code are in separate files.
• Any behavior that is described as "implementation defined" should be treated as a
machine (compiler) dependency.
• Pay attention to word sizes. Objects may be non-intuitive sizes, Pointers are not
always the same size as ints, the same size as each other, or freely interconvertible.
• Be sure to cast pointers back to the correct type before using them.
• Note that the size of an object does not guarantee the precision of that object.
• The integer constant zero may be cast to any pointer type.
• If you need pointers other than NULL, either allocate some storage or treat the pointer as
machine dependence.
• On some machines, a double may have less range or precision than a float.
• On some machines the first half of a double may be a float with similar value.
• Watch out for signed characters. If you must assume signed or unsigned characters,
comment them as SIGNED or UNSIGNED. Unsigned behavior can be guaranteed with
"unsigned char"
• Code that takes advantage of the two's complement representation of numbers on most
machines should not be used.
• Data alignment is also important.
• Specifically, a value should not be stored as one type and retrieved as another. An
explicit tag field for unions may be useful.
• Do not make assumptions about the parameter passing mechanism. especially pointer
sizes and parameter evaluation order, size, etc.
• Do not modify string constants.
• It is only portable to use <, <=, >, or >= to compare pointers when they both point in to (or
to the first element after) the same array. It is likewise only portable to use arithmetic
operators on pointers that both point into the same array or the first element afterwards.
• Side effects within expressions can result in code whose semantics are compiler-
dependent, since C's order of evaluation is explicitly undefined in most places..
• Be suspicious of numeric values appearing in the code ("magic numbers").
• Avoid preprocessor tricks. Tricks such as using /**/ for token pasting and macros that rely
on argument string expansion will break reliably.
• Become familiar with existing library functions and defines.
• Use lint when it is available.
• Suspect labels inside blocks with the associated switch or goto outside the block.
• Wherever the type is in doubt, parameters should be cast to the appropriate type. Always
cast NULL when it appears in non-prototyped function calls. Do not use function calls as
a place to do type cheating.
• Use explicit casts when doing arithmetic that mixes signed and unsigned values.
• The inter-procedural goto, longjmp, should be used with caution. Many implementations
"forget" to restore values in registers. Declare critical values as volatile if you can or
comment them as VOLATILE.
• Beware of compiler extensions. If used, document and consider them as machine
dependencies.
15 ANSI C
Whenever possible, write code to run under standard C, and use features such as function
prototypes, constant storage, and volatile storage.
15.1 Compatibility
Write code that is easy to port to older compilers.
Note that under ANSI C, the '#' for a preprocessor directive must be the first non-whitespace
character on a line. Under older compilers it must be the first character on the line.
Forward declarations of static functions should use a #define such as FWD_STATIC that is
#ifdeffed as appropriate.
An "#ifdef NAME" should end with either "#endif" or "#endif /* NAME */" not with
"#endif NAME". The comment should not be used on short #ifdefs, as it is clear from the code.
ANSI trigraphs may cause programs with strings containing "??" may break mysteriously.
15.2 Formatting
As const and volatile have strange binding rules, each const or volatile object should have a
separate declaration.
Prototyped functions merge parameter declaration and definition in to one list. Parameters should
be commented in the function comment.
/*
* 'bp': boat trying to get in.
* 'stall': a list of stalls, never NULL.
* returns stall number, 0 => no room.
*/
int
enter_pier (boat_t const *bp, stall_t *stall)
{
...
15.3 Prototypes
It is best to write in only one style (e.g., with prototypes). When a non-prototyped version is
needed, it is generated using an automatic conversion tool.
15.4 Pragmas
pragmas") may not. Required pragmas should be #ifdeffed so that compilation will abort if no
pragma is selected.
When pragmas are used, they must always be enclosed in machine-dependent #ifdefs. Pragmas
must always be #ifdefed out for non-ANSI compilers. Be sure to indent the '#' character on the
#pragma, as older preprocessors will halt on it otherwise.
16 Special Considerations
• Don't change syntax via macro substitution. It makes the program unintelligible to all but
the perpetrator.
• Don't use floating-point variables where discrete values are needed. Always test floating-
point numbers as <= or >=, never use an exact comparison (== or !=).
• You should write "around" compiler bugs only when you are forced to use a particular
buggy compiler.
• Do not rely on automatic beautifiers. Automatic beautifiers can only be applied to
complete, syntactically correct programs and hence are not available when the need for
attention to white space and indentation is greatest.
• Accidental omission of the second "=" of the logical compare is a problem. Use explicit
tests. Avoid assignment with implicit test.
abool = bbool;
if (abool) { ...
When embedded assignment is used, make the test explicit so that it doesn't get "fixed"
later.
• Explicitly comment variables that are changed out of the normal control flow, or other
code that is likely to break during maintenance.
• Use the register sparingly to indicate the variables that you think are most critical. In
extreme cases, mark the 2-4 most critical values as register and mark the rest as
REGISTER. The latter can be #defined to register on those machines with many
registers.
17 Lint
The use of lint on all programs is strongly recommended, and it is expected that most projects will
require programs to use lint as part of the official acceptance procedure.
18 Make
make recompiles only those modules that have been changed since the last time make was
used. It can be used to automate other tasks, as well. Some common conventions include:
all
clean
debug
depend
install
deinstall
mkcat
lint
run lint
print/list
shar
spotless
make clean, use revision control to put away sources. Note: doesn't remove Makefile,
although it is a source file
source
tags
rdist
file.c
In addition, command-line defines can be given to define either Makefile values (such as
"CFLAGS") or values in the program (such as "DEBUG").
19 Project-Dependent Standards
20 Conclusion
A set of standards has been presented for C programming style. Among the most important
points are:
• The proper use of white space and comments so that the structure of the program is
evident from the layout of the code. The use of simple expressions, statements, and
functions so that they may be understood easily.
• To keep in mind that you or someone else will likely be asked to modify code or make it
run on a different machine sometime in the future. Craft code so that it is portable to
obscure machines. Localize optimizations since they are often confusing and may be
"pessimizations" on other machines.
• Many style choices are arbitrary. Having a style that is consistent (particularly with group
standards) is more important than following absolute style rules. Mixing styles is worse
than using any single bad style.
As with any standard, it must be followed if it is to be useful. If you have trouble following any of
these standards don't just ignore them sort out the same with the project manager/ team leader.
S.No Check-List
1 Directory naming
2 File naming
3 File placement
FILE HEADER
FILE FOOTER
/*********************************************************************/
/* End of file sndcpllcprimitivehandler.c */
/*********************************************************************/
5 Header Files
Prototypes
Variable Declarations
Functions
Function commented
/*********************************************************************
* Purpose : To handle LL_RTS_INDICATION primitive *
6 * Inputs : *
* Return : *
*********************************************************************/
Usage
15
LL_RESET_IND_ST *llResetIndication_pst;
U8 cnt_u8=0;