Notice
This is a modification of the style guide provided by [suckless.org].
File Layout
- Comment with LICENSE
- Headers
- Macros
- Types
- Function declarations
- Include variable names
- For short files these can be left out
- Group/order in logical manner
- Global variables
- Function definitions in same order as declarations
- main
C Features
- Up to C99 without extensions
- POSIX.1-2008
- Declarations should not be mixed with statements
- Loop initial declarations should not used
- C style
/* */
comments should be used, not C++ style//
comments #if 0 #endif
must be used to comment out code, not/* */
- Variadic functions and macros are acceptable, but require safety
Blocks
{
on same line preceded by single space (except functions)}
on own line unless continuing statement (e.g.if else
)Blocks are used for single statements if and only if
An inner statement needs a block:
for (;;) { if (foo) { bar; baz; } }
Another branch of the same statement needs a block:
if (foo) { bar; } else { baz; qux; }
One exception to this rule is nested for loops like below:
for (i = 0; i < 64; ++i) for (j = 0; j < 32; ++j) for (k = 0; k < 16; ++k) { /* ... do stuff here ... */ }
Indentation and Line Length
- The maximum line length is 80 columns
- Tabs are used for indentation with a visual width 8-spaces
- An extra indent or two should be used when wrapping lines
- String literals used in error messages are an exception to these rules:
- This makes them easy to search for with grep
- Multiline string literals should be continued with
\
Functions
- Modifiers and the return type on their own line
- Function name and argument list on the next line
- Opening
{
must be on its own line (functions are special) - Functions not used outside translation unit must be static
Variables
Should be declared as close as possible to initialization/use
Global variables not used outside translation unit should be static
In declaration of pointers the * must be touching the variable name, not the type:
int *foo;
Keywords
- Space after
if
,for
,while
, andswitch
as these are not function calls - Space should not be used after the opening
(
and before the closing)
- Parentheses must be used with
sizeof
sizeof()
must be written as a function call since it acts like oneswitch
statements and their cases share the same indentation levelswitch
cases that FALLTHROUGH should be commented
Headers
- Include libc/system headers come first alphabetically
- If order cannot be alphabetical, a comment must explain
- There must be a blank line between system headers and project headers
- When writing and using local headers
- Include guards must be used
- Should be included alphabetically
User Defined Types
- Typedef is not used for structs which have fields meant to be accessed
- Typedef is allowed for opaque types, enums, and error codes
- Type names should be all lowercase
Handling Errors
Use Linux style gotos in a function that can fail and must cleanup multiple resources before exiting
Errors or failures should be returned from early rather than later in nested code:
Like so:
if (err) return;
Instead of:
if (success) { /* Do stuff */ } else { return; }
Enums vs #define
Use enums for values that are grouped semantically and #define otherwise:
#define MAXSZ 4096 #define MAGIC1 0xdeadbeef enum { DIRECTION_X, DIRECTION_Y, DIRECTION_Z };