Coding style guide - C/meta
Posted on 2004-04-26 by ivo :: /meta :: link
This document is Copyright © 2004 Ivo Timmermans. This document is licensed for distribution under a Creative Commons License. It is based on Fruit's Source Code Style, which was licensed under the artistic license.
<< Back to coding style index.
- Source file layout
- Function definitions
- Variables
- Function body
- Parentheses
- Placing assignments
- Boolean expressions
1. Source file layout
1. Line length
Lines may not exceed 78 characters. Do not write lines that are longer than 78 characters. It is always possible to wrap lines, and continue on the next line. It should never be necessary to indent more than about four levels deep. (This asserts that tabs count as if they were 8 characters.)
2. Copyright and license statement
At the head of each source file there should be a comment, which mentions the file name, its function in the program, a copyright and license statement. Always include at least one email address. Optional extra information, such as CVS Id tags, should follow the license. For notes on the layout of multiline comments, see below.
/* * foo.c - Frobnicate the foobar * Copyright (C) 2004 Ivo Timmermans <ivo@o2w.nl> * * License… * * $Id: foo.c,v 1.1 2004/01/10 12:34:56 ivo Exp $ */
Top-level inline documentation should be in a separate comment, after this one.
3. Preprocessor directives
Simple statements should be like this:
#include <stdio.h> #define CONSTANT 3
When nesting statements, such as
#ifdefs, put a tab after the # and the
rest of the line. Put a comment after the accompanying
#else and #endif to indicate which block
is terminated.
#ifdef SOMETHING # ifdef SOMETHINGELSE # define CONSTANT 4 # endif /* SOMETHINGELSE */ #endif /* SOMETHING */
4. Macros
There is no reason to make macros longer than 78 characters, they
can be wrapped with a backslash at the end of the previous line.
Creating a macro which uses local variables should be avoided, but
if absolutely necessary, wrap the macro in a do {
… } while (0)-loop. Always wrap macro
arguments in parentheses when the expansion could be
ambiguous.
#define MACRO(x, y) do { \
do_something_with(x); \
(y) = (x) << 4; \
} while (0)
5. Comments
Multiline comments should be formatted as follows, so that the vertical line of asterisks on the left is a clear indication that it is a comment.
/* * First paragraph of a multiline comment. * * Second paragraph of the comment. */
Simple comments following a statement should be separated from the statement with two spaces. The length of the entire line should not be more than 78 characters, put the comment on the preceding line if necessary (but put an empty line before it to improve readability).
frob(arguments); /* Frobnicate before it's too late! */
/* This comment is too long to fit on the next line. */
r = functioncall(with, arguments);
/*
* Do not read the code below, it is evil.
*
* Actually that's a lie.
*/
do_evil_stuff();
6. Documentation
Documentation for functions can be placed in a header file, along with their prototype declarations. This information can be extracted with tools such as doxygen to make nicely formatted documents; public functions are usually part of an API. Static functions will of course have their documentation alongside their definitions.
Comments on the inner workings of a function—for example the exact algorithm that is used—should be placed inline in the code, or above it in the source file.
foo.h:
/* Sort list alphabetically, returns the sorted list */ extern list_t *sort_list(const list_t *list);
foo.c:
/*
* Sort list alphabetically, using the modified bubblesort
* algorithm, which is defined in bubblesort.c.
*/
list_t *sort_list(const list_t *list) {
…
}
2. Function definitions
1. Declaration
Everything in the function declaration should be on one line. If the argument declaration doesn't fit in 78 characters, they should be separated at the commas. Precede the continuation line with two tabs (the continuation must not be on the same indentation level as the function body).
static struct somestruct *function(struct somestruct **argument,
struct someotherstruct *something, int foo, int blargh) {
Of course, if you need a long declaration such as the one above, you need to start thinking of using typedefs.
If a function takes no arguments, explicitly declare it with
function(void). If a function returns nothing,
explicitly declare it void function(…).
2. Placing braces
Braces are formatted using what looks like K&R style but is more regular. In particular, braces are put after a function declaration, not on a line of their own. So:
int main(int argc, char **argv) {
if (foo) {
bar;
}
return 0;
}
3. Variables
1. Naming
Use lowercase names for everything, using underscores if something needs multiple words. The only exception are preprocessor constants, which are all uppercase. Short names avoid tedious typing but do make the names descriptive of their content. Don't bother reusing local variables; the compiler will do that for you.
int i, fd, program_path; /* good */
int aFile, temp; /* bad */
Common sense applies: don't use i for storing the
return value of a function, don't use r as a counter.
Never use one variable for two different things.
2. Declarations
When declaring pointers, the asterisk shall be put next to the variable name, not next to the type name. This is because the asterisk is part of what is being declared, not of the type itself. Example:
char *p; /* good, should be read as “the content of p is a character” */
char* q; /* bad, “q is a character content of” */
The virtue of this becomes apparent when you regard:
char* p, q; /* what is the type of q? */
3. Initialization
The machine internal representation of a NULL-pointer does not have to be all-zeroes (but the C representation is always false). Thus, do not initialize structures with memset() or bzero():
memset(p, 0, sizeof *p); /* bad */
struct foo p0 = {0};
*p = p0; /* good */
4. Function body
1. Function length
A function should never have to be longer than about 50 lines (approximately two screenfuls on a standard terminal), including empty lines and any extra lines that are caused by wrapping. This excludes any documentation for the function, which should precede the function declaration. (Sometimes the documentation can be placed in header files, accompanying the prototype declaration.) Any function that requires more than 100 lines is probably badly designed.
2. Using braces
If possible, braces are omitted, except when either part of an
if (…) … else
… uses braces, then the other part will also use
braces:
if (foo) {
bar;
baz;
} else {
quux;
}
When using nested if statements, always put braces
around the inner code blocks, even if the inner if is
the only statement in that block. This means that possible
else-blocks of the outer if also get
wrapped.
if (foo) {
if (bar)
baz;
else
qux;
} else {
quux;
}
do …
while (…)-loops are formatted with
the while on the same line as the closing brace:
do {
statements;
} while (…);
3. How to indent
Indentation is always done using tabs. It is recommended that the tab length of your editor be set to something more reasonable than 8. I personally prefer 4, but the pleasant thing about tabs is that everyone can use their favourite indentation size.
4. Using tabs
Tabs are used only at the beginning of a line. If you feel a need to align other bits, use spaces. But rather don't align them at all, unless there's a very compelling reason to do so.
5. When to indent
Control statements and their body always have lines of their own, even if they are very short:
if (x)
y();
6. Line continuation
If a line is more than 78 characters long it should really be broken into bits. Conversely, if a line is shorter, do write it on a single line. Every line but the first should be given a single extra tab. If the line is a formula, then the operator at which you break the line should be the first character of the new line. Examples:
x = get_foobar(foo, bar, baz) + get_xyzzy(zxnrbl, quux)
+ get_zoo(bear, monkey, lion, penguin) + get_pets(cat, dog)
+ get_colours(red, green, blue, yellow);
7. Complex line continuation
There are two reasons to deviate from this rule: if the formula is exeptionally complex it may be better to give some parts an extra tab to show that they are in fact subordinate clauses to the main formula:
y = a
+ b
+ c1
* c2
* c3
* c4
+ d;
8. Control line continuation
The other reason is when a broken line is a control statement that is followed by a body:
if (foo + bar + baz
+ quux + xyzzy) /* an extra tab */
zxnrbl();
9. Empty lines
Use empty lines to indicate blocks of code that pertain to a specific operation, and to separate those that have different purposes. Always put an empty line after variable declarations and indented blocks.
void function(void) {
int a, b = 0;
a = do_something();
if (a) {
b = do_something_with_a();
}
do_something_with_a_and_b(a, b);
}
5. Parentheses
1. Using parentheses
If possible parentheses should be omitted, except when this
evokes a warning from the compiler. In particular,
return and sizeof are not
functions!
int x;
x = sizeof x; /* no parentheses here */
return x; /* nor here */
The only reason why sizeof often needs parentheses
is that it is often used with type expressions, which need
parentheses just like they do in typecasts.
2. Placing parentheses
Parentheses always cuddle up to the function they follow, but
there's a space between a control statement (for,
if and while) and the parenthesis
following it. There are no spaces directly after an opening
parenthesis, or directly before a closing parenthesis:
if (foo) /* one space */
bar(); /* no space here */
qux(a + b); /* no spaces inside the parentheses */
There is a space between a control statement and the opening parenthesis, but not for function calls.
if (foo) /* a space */
bar(4); /* no space */
for (…) { /* a space */
baz(qux); /* no space */
}
3. Using spaces
In formulas be generous with spaces, they make things more readable:
return x * (a + b) * y;
When writing comma delimited lists, such as in function arguments, place a space only after each comma.
foo(a, b); /* good */
bar(a,b); /* bad */
bar( a , b ); /* bad */
4. Typecasts
When doing typecasts, put a space between the type and the object being cast:
int a = (int) p;
Write complex (pointer) types like you would in a declaration:
struct something **a;
a = (struct something **) p;
6. Placing assignments
Avoid assignments in truth statements—if only because they often require extra parentheses to avoid compiler warnings.
r = read(fd, buf, sizeof buf);
if (r == -1)
b0rk();
7. Boolean expressions
Use the fact that boolean expressions in C mean testing for non-zero-ness. In particular, avoid pointless noise like:
if (p != NULL) …
if (i == 0) …
These should be rewritten as:
if (p) …
if (!i) …
… because C already does such a check internally.
