- Max line width is 80 columns.
- Indentation width is 4 spaces.
- Never use tabs.
- Consecutive declarations must be aligned
- Curly braces for functions and
for
,while
,if
,else
,switch
statements are the same as in the Linux code style. - No space between function name and it's arguments list in parentheses.
- Exactly one space between
for
,while
,if
,switch
statement and it's expression in parentheses. - Every
case
is on the same level as it'sswitch
statement. for
,while
,if
,else
,switch
statements has no curly braces on the corresponding code block if block contains only one operator (see Curly braces).- Function declaration and prototype declared in one line. Type, name and arguments list are on the same line.
- Too long function arguments list carried over and indented one level relatively to function name. The same is for function declaration, prototype and invocation.
- Line breaking operator (e.g.
+
,=
,%
,?
) must be carried over with new line. (clang-format
BreakBeforeBinaryOperators: All, BreakBeforeTernaryOperators: true) - No more than two empty lines anywhere.
- Pointer declaration and dereferencing asterisk (
*
) as long as addressing ampersand (&
) are adjacent to the data or function name, not to type name. - No
#ifndef __HEADER_H__
include guards and no includes in headers. - No executable code in headers. Let defines, types, typedefs and functions prototypes only.
- Naming is lowercase with
underscores_between_words
andUPPERCASE_FOR_DEFINES
. - Minimum of typedefs.
- Minimum of comments (except for documenting software like doxygen).
Classic C programming approach is procedural programming and the best naming style for this is the following.
- Minimum of typedefs, better not to use typedefs at all.
spaces_between_words
in function and variable names.- All names are lowercase, if other is not necessary.
- Preprocessor definitions are
UPPERCASE_ONLY
. - External preprocessor definitions
_STARTS_WITH_UNDERSCORE
and defined on compiler invocation as-D_DEFINITION_NAME
.
Completely bad:
#define errcode 15;
#define myType int;
int variableName;
int another_Variable_Name;
TypedefedStruct TypedefedVariableName;
void *functionName(myType arg_1_name, char *arg_2);
void AnotherFunctionName(int arg_1, void arg_2);
Sort of (formal) good:
#define ERR_CODE_NO_ERROR 0;
int variable_name;
char *word;
float disp;
struct some_struct struct_variable;
void *function_name(size_t arg_name1, char *arg2);
Sometimes it is better to shorten some names a little, especially if it has very small scope and pattern designation like i
or j
iterator in a loop. Shorten names are not actually bad. Linux code style has better explanation for naming.
Braces example
Good:
int *function(int arg1, int *arg2)
{
int *a = malloc(arg1, sizeof(int))
while (arg1-- > 0) {
if (arg2[arg1] & MASK) {
a[arg1] = arg2[arg1];
a[arg1] += arg1 >= 0 ? arg2[arg1-] : 0;
} else if (arg2[arg1] & ANOTHER_MASK) {
free(a);
set_my_errno(ERR_CODE);
return 0;
}
}
}
if (expression)
function();
else
other_function();
if (expression)
function();
else {
other_function();
some_other_function();
}
if (expression) {
function();
other_function();
} else
some_other_function();
if (expression)
operator();
/* Single line loop is ok when no operators in body */
while ((list = list->next));
Bad:
if (expression) {
function();
} else {
other_function();
some_other_function();
}
if (expression) {
function();
other_function();
} else {
some_other_function();
}
/* Seems like you are trying to hide something */
if (expression) operator();
/* Ugly */
while ((list = list->next))
;
Struct declaration
struct mystruct {
int field1;
int *field2;
}
Struct and array initialization is not too strict. You can do either
struct mystruct aaa = {
.field1 = 0,
.field2 = 0,
};
or
struct mystruct aaa = {.field1 = 0, .field2 = 0};
as you wish, depending on how long the initialization list is and how readable it could be. But following examples looks ugly. Please don't write code in such way:
struct mystruct aaa = {.field1 = 0,
.field2 = 0};
struct mystruct bbb =
{
.field1 = 0,
.field2 = 0,
};
struct mystruct aaa = { .field1 = 0, .field2 = 0 };
Do not omit argument names in function prototypes. They may serve you as a quick reference, especially since no documentation system is used. Use the same argument names as in function declaration itself.
Bad:
int function(int, float, char *);
Good:
int function(int arg1, float arg2, char *arg3);
If you have a function prototype or a function declaration more than 80 characters long... do your best to avoid this! But if there is an essential reason to have such an ugly function, then just break arguments list and align next lint to the function name with one extra level of indent.
int function_with_intentionally_long_name(struct with_long_name argument1,
float arg2, char *not_too_long_name);
// |---^ - Indentation
void *shorter_name(struct with_long_name hehe, int fits, char * const and_this,
char *but_this_not, char *and_this_is_going_to_be_here,
struct okay lets_go_crazy_with_this, int awww);
// |---^ - Indentation
char * const char *function(struct mystruct arg1, int arg2, char *arg3, int arg4,
float arg5);
// |---^ - Indentation
The same is for executable lines;
int sum_of_variables = data_struct->array[i][j] + meaningful_variable
+ length < size ? length : 0;
// |---^ - Indentation (new line with linebreaking operator)
int i_tried_of_this_stupid_longnaming
= max(0, data_struct->array[i][j]->holy_shit_how_long_this_is);
// |---^ - Indentation (new line with linebreaking operator)