Add example of if..else brace style
Clarify anonymous struct usage
Add style for struct and union declarations
This is my style guide for C projects. The main guiding principles are:
This guide aims to be more exhaustive and specific than is always necessary - in general if you skim this guide and then try to match the style of nearby code, you'll be okay.
The style guidelines are presented with RFC 2199 style language, using the keywords SHOULD, MUST, etc, to indicate required levels of compliance.
Send questions and feedback to ~sircmpwn/public-inbox@lists.sr.ht.
Table of contents
root = true
[*.{c,h}]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
indent_style = tab
indent_size = 8
max_line_length = 80
Place this file at .editorconfig
in the root of your project to automatically
apply these rules to your editor.
Programmers MUST indent with 8-column tabs, instead of spaces.
Programmers SHOULD hard wrap lines to 80 columns.
See splitting long lines for specific advice on splitting up long declarations, expressions, and so on.
Programmers MUST use const to constrain their pointer usage.
Programmers MUST use the most appropriate integer types for their situation.
stdint.h
to use integers with a specified storage size.uintmax_t
and intmax_t
to store any integer.size_t
for array indicies, the value of sizeof, and so on.limits.h
includes constants for the maximum and minimum bounds of many
types, use it to assert your assumptions or declare arrays (e.g. PATH_MAX
).Programmers MUST use enums over #define or magic constants.
Declare flags with bitwise arithmetic:
enum my_enum {
MY_ENUM_FLAG_A = 1 << 0,
MY_ENUM_FLAG_B = 1 << 1,
MY_ENUM_FLAG_C = 1 << 2,
};
For easier copy/paste.
Programmers SHOULD use assert to enforce their assumptions.
If you expect a pointer to be non-null, assert it. If you expect an integer to be within certain bounds, assert it. If you expect a buffer to be of a certain size, assert it.
Use asserts for programmer errors, not normal runtime errors. If an assertion ever fails, the resolution is always to update the code.
Assertions must not have side-effects. The following example is incorrect:
assert(write(...) >= 0);
Programmers SHOULD prefer to stack-allocate resources.
Programmers SHOULD prefer calloc for heap-allocated resources.
Programmers SHOULD NOT use language extensions, such as gcc-specific features.
Programmers MUST use preprocessor tests before using language extensions.
#error
branch if no portable option exists.Programmers MUST NOT use libc extensions, such as glibc-specific features.
man 3p funcname
._GNU_SOURCE
or _DEFAULT_SOURCE
, instead use
_POSIX_C_SOURCE
or _XOPEN_SOURCE
. See
feature-test-macros(7).Programmers MUST NOT use wide characters.
Programmers SHOULD NOT use inline functions.
Programmers SHOULD NOT use macros.
Macros introduce additional complexity by being able to break out of the call frame sandbox, accessing locals and changing your code's behavior in unpredictable ways.
C has a second-class macro system, making them difficult to write and difficult to debug. Hacks like extra parenthesis around everything, backslashes to continue on multiple lines, useless loops and branches to introduce scopes - all make your code more difficult to read and understand.
Macros are opaque - their behavior is not inferable from code which invokes them. Example: which of these are macros, and which are function calls?
begin(ctx);
do_work(ctx);
send_notification(ctx);
end(ctx);
Spoiler: you can't tell.
Programmers SHOULD NOT use typedef.
Programmers SHOULD NOT use pointer arithmetic.
strstr
to an index.Programmers SHOULD NOT use global variables.
Programmers MUST use braces where the language makes them optional.
Single-line if statements, loops, etc, must use braces. It's a small loss for ergonomics with a tangible benefit for error prevention.
Programmers MUST place opening braces on the same line.
Correct:
if (cond) {
/* ... */
}
if (cond) {
/* ... */
} else if (other cond) {
/* ... */
} else {
/* ... */
}
for (...) {
/* ... */
}
while (...) {
/* ... */
}
do {
/* ... */
} while (...);
Incorrect:
if (cond)
{
/* ... */
}
if (cond)
{
/* ... */
}
else if (other cond)
{
/* ... */
}
else
{
/* ... */
}
for (...)
{
/* ... */
}
while (...)
{
/* ... */
}
do
{
/* ... */
}
while (...);
Programmers MUST place opening braces on the next line for function declarations.
Correct:
static int
my_function(parameters...)
{
/* function body */
}
Incorrect:
static int
my_function(parameters...) {
/* function body */
}
Programmers MUST align case branches with the switch statement.
Correct:
switch (...) {
case FOOBAR:
/* ... */
break;
case FOOBAZ:
/* ... */
break;
default:
/* ... */
break;
}
Incorrect:
switch (...) {
case FOOBAR:
/* ... */
break;
case FOOBAZ:
/* ... */
break;
default:
/* ... */
break;
}
Programmers MUST use "fallthrough" comments.
Example:
switch (...) {
case FOOBAR:
/* ... */
/* fallthrough */
case FOOBAZ:
/* ... */
break;
default:
/* ... */
break;
}
This is not necessary when several "case" statements follow the same branch:
switch (...) {
case FOOBAR:
case FOOBAZ:
/* ... */
break;
default:
/* ... */
break;
}
For single line or inline comments, programmers MUST use /* */
:
Correct:
/* Coordinates: */
int x = 0; /* x coordinate of foobar */
int y = 0; /* y coordinate of foobar */
Incorrect:
// Coordinates:
int x = 0; // x coordinate of foobar
int y = 0; // y coordinate of foobar
For multi-line comments, programmers MUST use /* */
, MUST wrap to 80
columns, and MUST insert a space and a * on continuation lines.
Correct:
/*
* Quae et nisi et a amet est quae est. Doloremque eum praesentium error quas
* autem. Modi quo suscipit adipisci. Fugiat vero non neque neque velit qui.
* Facilis quos reprehenderit et beatae quaerat sunt sapiente.
*/
Permissible:
/* Quae et nisi et a amet est quae est. Doloremque eum praesentium error quas
* autem. Modi quo suscipit adipisci. Fugiat vero non neque neque velit qui.
* Facilis quos reprehenderit et beatae quaerat sunt sapiente. */
Incorrect:
/* Quae et nisi et a amet est quae est. Doloremque eum praesentium error quas
* autem. Modi quo suscipit adipisci. Fugiat vero non neque neque velit qui.
* Facilis quos reprehenderit et beatae quaerat sunt sapiente.
*/
/*
* Quae et nisi et a amet est quae est. Doloremque eum praesentium error quas
* autem. Modi quo suscipit adipisci. Fugiat vero non neque neque velit qui.
* Facilis quos reprehenderit et beatae quaerat sunt sapiente. */
/*
* Quae et nisi et a amet est quae est. Doloremque eum praesentium error quas
* autem. Modi quo suscipit adipisci. Fugiat vero non neque neque velit qui.
* Facilis quos reprehenderit et beatae quaerat sunt sapiente.
*/
// Quae et nisi et a amet est quae est. Doloremque eum praesentium error quas
// autem. Modi quo suscipit adipisci. Fugiat vero non neque neque velit qui.
// Facilis quos reprehenderit et beatae quaerat sunt sapiente.
Programmers SHOULD NOT comment excessively, preferring to write code which can be understood without clarification.
Programmers MUST declare functions with the following style:
static int
my_function(parameters...)
{
/* function body */
}
git grep '^my_function'
Programmers MUST declare prototypes with the following style:
int my_function(parameters...);
Programmers SHOULD use goto to deduplicate error handling.
Programmers MUST add include guards.
Use the format ${PROJECT}_${HEADER_PATH}_H
for the macro.
Example:
#ifndef MYPROJECT_MYSUBDIR_FOOBAR_H
#define MYPROJECT_MYSUBDIR_FOOBAR_H
/* declarations... */
#endif
Programmers MUST NOT use #pragma once.
This is a GCC extension, see features to avoid.
Headers MUST include only prototypes, type declarations, and documentation.
Do not include inline functions or macros, see features to avoid.
Programmers MUST alpha-sort their headers, and group by locality.
<>
) headers, then internal headers (""
),
then sort them alphabetically within their groups.Programmers SHOULD NOT include other headers.
If you need a struct with a defined storage type (for inlining), you MAY include the header which defines it.
If you need a struct to take a pointer to, you SHOULD forward declare an opaque struct.
struct my_struct;
void unrelated_module_state_add(const struct my_struct *ref);
Headers which define standard types (stdint.h
, stddef.h
, etc) are excepted
from this rule.
Programmers MUST place spaces between control flow keywords and parenthesis.
Correct:
if (...) {
}
for (...) {
}
while (...) {
}
Incorrect:
if(...) {
}
for(...) {
}
while(...) {
}
Programmers MUST NOT place inner spaces in parenthesized expressions.
Correct:
function_call(1, 2, 3);
if (x == y);
Incorrect:
function_call( 1, 2, 3 );
if ( x == y );
Programmers MUST place spaces around binary operators.
Correct:
function_call(x + y * 2);
Incorrect:
function_call(x+y*2);
Programmers SHOULD NOT split lines which are less than 80 columns.
Programmers MUST double-indent continuation lines for new scopes.
Correct:
if (is_valid_foobar(possible_foobar)
&& get_number_of_foobars(possible_foobar) > 10
&& is_application_ready()) {
/* Do work */
}
int
do_foobar_work(struct foobar *foo, struct foobar *bar,
struct foobar *baz, struct foobar *bet)
{
/* Do work */
}
Incorrect:
if (is_valid_foobar(possible_foobar)
&& get_number_of_foobars(possible_foobar) > 10
&& is_application_ready()) {
/* Do work */
}
int
do_foobar_work(struct foobar *foo, struct foobar *bar,
struct foobar *baz, struct foobar *bet)
{
/* Do work */
}
Programmers MUST single-indent continuation lines in the same scope.
Correct:
int
main(int argc, char *argv[])
{
do_program_work("hello world",
argc, argv);
return 0;
}
Incorrect:
int
main(int argc, char *argv[])
{
do_program_work("hello world",
argc, argv);
return 0;
}
Programmers MUST place operators on the next line.
Correct:
if (is_a_foobar(possible_foobar)
&& get_number_of_foobars(possible_foobar) > 10
&& is_application_ready()) {
/* Do work */
}
Incorrect:
if (is_a_foobar(possible_foobar) &&
get_number_of_foobars(possible_foobar) > 10 &&
is_application_ready()) {
/* Do work */
}
Programmers MUST NOT align parameters with the opening '('.
Incorrect:
int do_work(struct foobar *foo,
struct foobar *bar,
struct foobar *baz,
struct foobar *bet);
Correct:
int do_work(struct foobar *foo, struct foobar *bar,
struct foobar *baz, struct foobar *bet);
Programmers SHOULD split long string literals into multiple lines.
When long strings hit 80 columns, terminate the string and resume it on the following line.
fprintf(stderr, "%s:%d:%d: error: every foo must have a corresponding "
"'bar' declaration.", filename, lineno, colno);
Programmers SHOULD split long lines with left-right balance.
Try to make it "look good" by drawing a vertical line at 40 columns and "balancing" characters on either side. This is a subjective rule.
Programmers MUST declare structs and unions with the {
on the first line,
and };
on its own line.
Correct:
struct my_struct {
int field_a;
int field_b;
int field_c;
};
union my_union {
int i;
long l;
double d;
};
Incorrect:
struct my_struct
{
int field_a;
int field_b;
int field_c;
};
union my_union
{
int i;
long l;
double d;
};
Programmers MUST place the name of an inline struct or union field on the
same line as }
and ;
.
Correct:
struct my_struct {
struct {
int a, b,c;
} nested_struct;
struct {
int a, b, c;
}; /* Anonymous */
union {
int a, b,c;
} nested_union;
};
Incorrect:
struct my_struct {
struct {
int a, b,c;
}
nested_struct;
union {
int a, b,c;
}
nested_union;
};
Programmers MUST place * next to the binding when declaring pointers.
Correct:
void do_work(struct my_struct *in);
struct my_struct *foobar = NULL;
Incorrect:
void do_work(struct my_struct* in);
struct my_struct* foobar = NULL;
The operator has right associativity. When declaring multiple variables in one statement, the asterisk will be misleading:
struct my_struct* foobar, foobaz;
The second variable is not a pointer. For consistency, however, even single-variable declarations must place the asterisk to the right.
Programmers MUST USE a typedef for function pointers which are the parameters to other functions.
Correct:
typedef void (*foobar_callback_func)(struct foobar *, void *);
void foobar_run(struct foobar *fb, foobar_callback_func cb, void *user);
Incorrect:
void foobar_run(struct foobar *fb,
void (*cb)(struct foobar *, void *), void *user);
Programmers SHOULD name public functions with the following format:
$NAMESPACE_$VERB(...);
$NAMESPACE_$NOUN_$VERB(...);
For example:
void example_run(...);
void example_foobar_update(...);
Programmers SHOULD omit the namespace for static functions.
However, the ordering of noun/verb is more subjective:
static void process_events(...);
static struct foobar *foobar_from_foobaz(...);
Programmers MUST use the verbs "create" and "destroy" for heap objects:
struct my_struct *my_struct_create(...);
void my_struct_destroy(struct my_struct *in);
Programmers MUST use the verbs "init" and "finish" for stack objects:
void my_struct_init(struct my_struct *in, ...);
void my_struct_finish(struct my_struct *in);
Programmers SHOULD use nouns to name variables.
Programmers MAY use short variable names if their usage is clear.
read
et al "n", sizes
"sz", characters "c" or "ch", strings "s" or "str", operands named "val", etc.