Style guide for ANSI C projects
Version 1
Comment usage
All comments are block style. When continuing onto multiple lines, prepend *
at the start of each new line, like so:
/* start of a comment
* continuing a new line
*/
Apply a comment after #endif
directives referencing the corresponding identifier, when the #if
block is lengthy (use discretion), like so:
#ifndef WIN32_LEAN_AND_MEAN
#error "no"
/* ... */
#endif /* WIN32_LEAN_AND_MEAN */
To section out portions of code in exclusion from compilation, use the #if 0
trick, like so:
void foo( void )
{
int i, j;
/* ... */
#if 0
/* The_BAD_Code (!!!) */
#endif
}
Identifier naming
Use snake_case
for all identifiers, in uppercase for constant values and lowercase otherwise. Note that const
variable declarations are not considered ‘constant’ for this purpose. All identifiers exposed by the CPP should be in uppercase.
Always prefer shorter identifiers to longer ones. Do not exceed 31 characters in symbol names, as this is considerate to memory-constrained compilers. Use comments to explain identifiers instead.
#define MY_DEFINE 111
#define MAC_RO_FO_SHO(xx) \
(xx ? 69 : 420)
/* xx is not exposed by the CPP, so it is not uppercase */
const int examp = 13;
void far_func( int, int* );
int sigh( void )
{
int x;
far_func( 42, &x );
if( examp > x )
{
x *= MAC_RO_FO_SHO( examp );
x /= 2;
}
return x + MYDEFINE;
}
Whitespace
Always use hard tabs for indentation. Configure auto-formatters to treat sources with 8-character-wide tabs, so that editors will display well with this width or less. Do not exceed 79 characters in width, as this is considerate to terminal editing. The exception to this rule from linux applies, so disregard the rule for constant char*
expressions.
Separate blocks with blank lines. Collections of similar adjacent code can be separated from one another with blank lines as well (use discretion).
A single space should follow an opening parenthesis and precede a closing parenthesis. Parenthetical statements should have their identifiers or keywords immediately followed by the opening parenthesis (ergo, no space in between). Square brackets should not have any spacing surrounding them.
Prefix and postfix operators should immediately precede or follow their identifiers, respectively. Align the indentation of case
statements with their corresponding switch
keywords.
foo++;
++bar;
switch( baz )
{
case 'A':
bar++;
break;
case 'B':
bar--;
break;
default:
bar = 1;
break;
}
Curly braces
Allman-style bracing is used throughout, however Curly braces for initialiser lists should have the opening brace on the same line as the equal sign =
. Always use braces with block statements, even when they are one line (also, consider ternary conditionals).
const int sup[5] = {
1, 2, 3, 4, 5
};
Control flow
Use falsey values to indicate success wherever possible, but note deviations from this wherever necessary. Store the result of boolean expressions as int
s, if necessary, but avoid storing boolean values wherever possible.
Terminate case
statements with break
statements unless there is an intentional fall-through. Comment to note fall-throughs.
Use prefix increment/decrement instead of postfix inside for
loops, as this is considerate to antique compilers.
Use discretion to apply ternary conditional expressions in place of unwieldy conditional blocks.
extern struct state s;
while( !mainloop( &s );
switch( bla )
{
case '-':
case '_':
case '=':
return 0;
break;
case '+':
ble++;
/* fall-through */
default:
ble++;
break;
}
int foobar( void )
{
volatile int reee = 5555;
return 55555 >= reee ? 32 : 640;
}
Types and C ‘namespaces’
Do not typedef
struct
or enum
definitions. Do not assume any typing about enum
s and likewise do not use enum
names as types. Additionally, do not name enum
s (though they may be ‘named’ informally with a comment in its place). Use typedef
s to specify function pointer signatures, and to alias primitives for flexibility. C’s struct
and enum
keywords constitute namespaces (unrelated to C++ namespace
s) that distinguish them from primitives.
/* incorrect */
enum mycoll
/* correct */
enum /* mycoll */
{
MYCOLL_FOO, MYCOLL_BAR, MYCOLL_BAZ
};
/* incorrect */
enum mycoll foo = MYCOLL_BAZ;
/* correct */
int foo = MYCOLL_BAZ;
/* incorrect */
typedef struct
typedef struct blah
/* correct */
struct blah
{
int a, b;
char c[5];
/* incorrect */
} blah_t;
/* correct */
};
/* incorrect */
typedef struct blah blah_t;
/* correct */
typedef void (*myfunc)( int, int );
typedef u16 mapid_t;