Epitech C Coding Style
Epitech C Coding Style
C Coding Style
Keep your code nice and clean
3.4
The Epitech Coding Style is a set of rules, guidelines and programming conventions that has been created
within the school, and that you have to respect.
It applies to:
The Coding Style is a purely syntactic convention, so it can not be used as an excuse if
your program does not work!
It is compulsory on all programs written in C as part of Epitech projects, regardless of the year or unit.
It applies to all source files (.c) and headers (.h), as well as Makefiles.
Although the Coding Style is not required in all projects, this is not a reason for not always
sequencing and structuring your code!
Most of the rules in this Coding Style apply to all languages, so it can be useful when
you’re doing projects in different languages.
It’s easier and quicker to follow the guide style from the beginning of a project rather
than to adapt an existing code at the end.
The existence of this Coding Style is justified by the need to standardize the writing of programs within the
school, in order to facilitate group work.
It is also an excellent way to encourage structuring and clarity of the code and thus facilitate :
• its reading,
• its debugging,
• its maintenance,
• its internal logic,
• its reuse,
• writing tests,
• adding new features . . .
When you are facing a choice and you do not know what decision to make, always ask
yourself which one helps to make your code clearer, ergonomic and flexible.
1
However, if you provide a complete, relevant, accurate justification with a long-term view (cleanliness,
legibility, code flexibility, optimization, etc.), you can infringe some of the Coding Style points.
The relevance of this justification is left to the discretion of the proofreader, so it is prefer-
able to present a strong argumentation or to abstain.
In case of uncertainty or ambiguity in the principles specified in this document refer to your local education
manager.
This document is inspired by the Linux Kernel Coding Style , and is freely adapted from
Robert C. Martin’s excellent book Clean Code.
2
O-
_ _ _ FILES
___ ORGANIZATION _____
+_ _O1-
_ _ _CONTENTS
_ _ _ _ _ _ _ OF THE DELIVERY FOLDER _____
Your delivery folder should contain only files required for compilation.
This means no compiled(.o, .gch, .a, .so, . . . ), temporary or unnecessary files (*~ * #, *.d,
toto,. . . ).
+_ _O2-
_ _ _FILE
_ _ _EXTENSION
____ _____
+_ _O3-
_ _ _FILE
_ _ _COHERENCE
____ _____
A source file should match a logical entity, and group all the functions associated with that entity.
Beyond 5 functions in your file, you should probably subdivide your logical entity into
several sub-entities.
+_ _O4-
_ _ _NAMING
_ _ _ _ _ _ FILES
_ AND FOLDERS _____
The name of the file should define the logical entity it represents, and thus be clear, precise, explicit and
unambiguous.
For example, the string.c or algo.c files are probably incorrectly named.
Names like string_toolbox.c or pathfinding.c would be more appropriate.
All file names and folders should be in English, according to the snake_case convention (that is, composed
only of lowercase, numbers, and underscores).
Abbreviations are tolerated to the extent that they can significantly reduce the size of
the name without losing the meaning.
3
G-
_ _ _GLOBAL
___ SCOPE _____
+_ _G1-
_ _ FILE
_ _ _ _HEADER
____ _____
The source files (.c,.h, Makefile,. . . ) should always start with the standard header of the school.
This header is created in Emacs using the C-c C-h command.
/*
** EPITECH PROJECT , $YEAR
** $ N A M E _ O F _ THE_PROJECT
** File description :
** No file there , just an epitech header example
*/
+_ _G2-
_ _ _SEPARATION
_ _ _ _ _ _ _ OF FUNCTIONS _____
Inside a source file, one and only one empty line should separate the implementations of functions.
+_ _G3-
_ _ _INDENTATION
_______ OF PRE-PROCESSOR DIRECTIVES _____
4
+_ _G4-
_ _ _GLOBAL
_ _ _ _ _ _VARIABLES
_ _____
A variable is called constant if and only if it is correctly marked as such with the const
keyword. Watch out, this keyword follows some particular and sometimes surprising
rules!
+_ _G5-
_ _ _STATIC
_______ _____
Global variables and functions that are not used outside the compilation unit to which they belong should
be marked with the static keyword.
5
F-_ _FUNCTIONS
_ ___ _____
+_ _F1-
_ _COHERENCE
_ _ _ _ _ _ _ _ OF FUNCTIONS _____
A function should only do one thing, not mix the different levels of abstraction and respect the principle
of single responsibility (a function must only be changed for one reason).
For example, a call to malloc(), a call to allocate_user() and a call to create_user() have
3 different levels of abstraction.
+_ _F2-
_ _ NAMING
_ _ _ _ _ _ _FUNCTIONS
_ _____
The name of a function should define the task it executes and should contain a verb.
For example, the voyals_nb() and dijkstra() functions are incorrectly named.
get_voyals_number() and search_shortest_path() are more meaningful and precise.
All function names should be in English, according to the snake_case convention (meaning that it is com-
posed only of lowercase, numbers, and underscores).
Abbreviations are tolerated if they significantly reduce the name without losing mean-
ing.
+_ _F3-
___NUMBER
_ _ _ _ _ _OF
_ COLUMNS _____
The length of a line should not exceed 80 columns (not to be confused with 80 characters!).
+_ _F4-
_ _ _NUMBER
_ _ _ _ _ _OF
_ LINES _____
6
If the body of a function exceeds 20 lines, it probably does too many tasks!
The maximum length of a function is inversely proportional to the complexity and indentation level of
that function. case-statement , where you have lots of small things for a lot of different cases, it’s OK to
have a longer function.
+_ _F5-
_ _ ARGUMENTS
________ _____
+_ _F6-
___COMMENTS
_ _ _ _ _ _ _ INSIDE A FUNCTION _____
7
+_ _F7-
_ _ NESTED
_ _ _ _ _ _ FUNCTION
__ _____
Nested functions are an extension of the GNU C standard which is not allowed because it increase com-
plexity.
8
L-_ _LAYOUT
_ ___ INSIDE A FUNCTION SCOPE _____
+_ _L1-
_ _CODE
_ _ _ _ _LINE
_ _ _CONTENT _____
a = b = c = 0; /* L1 violation */
a ++; b ++; /* L1 violation */
if (( ptr = malloc ( sizeof ( struct my_struct ) ) ) != NULL ) /* L1 violation */
if ( cond ) return ( ptr ) ; /* L1 violation */
a = do_something () , 5; /* L1 violation */
+_ _L2-
_ _ INDENTATION
________ _____
+_ _L3-
_ _ SPACES
________ _____
However, there will be no space between the name of a function and the opening parenthesis or after a
unary operator.
All binary and ternary operators should be separated from the arguments by a space on both sides.
9
+_ _L4-
___CURLY
_ _ _ _ BRACKETS
___ _____
Opening curly brackets should be at the end of their line, except for functions where they must be placed
alone on their line.
Closing curly brackets should always be alone on their line, except in the case of an else statement.
+_ _L5-
_ _ VARIABLE
_ _ _ _ _ _ _ _DECLARATION _____
Nothing prevents you from declaring and assigning a variable on the same line.
biggest = MAX (a , b ) ;
smallest = MIN (a , b ) ;
long rest ; /* L5 violation */
while ( smallest > 0) {
rest = biggest % smallest ;
biggest = smallest ;
10
smallest = rest ;
}
return ( a ) ;
}
+_ _L6-
_ _ LINE
_ _ _ _JUMPS
____ _____
A line break should separate the variable declarations from the remainder of the function.
No other line breaks should be present in the scope of a function.
int sys_open ( char const * path )
{
int fd = thread_reserve_fd () ;
struct filehandler * fhandler = NULL ;
/* OK */
if ( fd < 0)
return ( -1) ;
if ( fs_open ( path , & fhandler ) ) {
thread_free_fd ( fd ) ;
return ( -1) ;
}
/* L6 violation */
t h r e a d _ s et_ fd_ha ndle r ( fd , fhandler ) ;
return ( fd ) ;
}
V-
_ _ _VARIABLES
___ AND TYPES _____
+_ _V1-
_ _ NAMING
_ _ _ _ _ _ _IDENTIFIERS
_ _____
All identifier names should be in English, according to the snake_case convention (meaning it is composed
exclusively of lowercase, numbers, and underscores).
11
Abbreviations are tolerated as long as they significantly reduce the name length without
losing meaning.
The type names defined with typedef should end with _t.
The names of macros and global constants and the content of enums should be written in UPPER_CASE.
# define IS_PAGE_ALIGNED ( x ) (!(( x ) & ( PAGE_SIZE - 1) ) ) /* OK */
enum arch { /* OK */
I386 = 0 ,
X86_64 ,
ARM ,
ARM64 ,
SPARC ,
POWERPC ,
};
const float PI = 3.14159; /* OK */
typedef int age ; /* V1 violation */
typedef struct int_couple pixel_t ; /* OK */
+_ _V2-
_ _ _STRUCTURES
_______ _____
Variables could be grouped together into a structure if and only if they form a coherent entity.
Structures must be kept as small as possible.
struct person { /* OK */
char * name ;
unsigned int age ;
float salary ;
};
+_ _V3-
_ _ _POINTERS
_______ _____
The pointer symbol (*) should be attached to the associated variable, with no spaces.
int * a ; /* V3 violation */
int * a ; /* OK */
12
int a = 3 * b ; /* OK */
int strlen ( char const * str ) ; /* OK */
13
C-_ _CONTROL
_ ___ STRUCTURE _____
+_ _C1-
_ _ CONDITIONAL
________ BRANCHING _____
A conditionnal block (while,for,if,else,...) should not contain more than 3 branchings, excluding error
handling.
Instead, use an array of pointers to function or a switch. Take care to choose the most
suitable one (you may be asked for a justification).
If you need multiple levels of branching, you probably need to refactor your function
into sub-functions.
if (....) /* OK */
do_something () ;
else if (...)
do_s omething_else () ;
else
do_s omething_more () ;
if (....) /* C1 violation */
do_something () ;
else if (...)
do_s omething_else () ;
else if (...)
do_s omething_more () ;
else
do_o ne_last_thing () ;
while (....) /* OK */
if (...)
14
else if branching add one more level of branching than you could expect.
// This code
if (...) /* C1 violation */
do_something () ;
else if (...)
do_s omething_else () ;
else if (...)
do_o ne_last_thing () ;
// is unfolded as this
if (....) /* C1 violation */
do_something () ;
else {
if (...)
do_ something_else () ;
else {
if (...) {
do_one_last_thing () ;
}
}
}
If ever you need to disrepect this rule, you could probably compute the cyclomatic com-
plexity of your function to justify it. . .
15
+_ _C2-
_ _ _TERNARY
_______ _____
Ternaries are allowed as far as they are kept simple and readable, and they do not obfuscate code.
+_ _C3-
_ _ _GOTO
_______ _____
Your code should not contain the goto keyword, especially because it can very quickly participate in the
creation of infamous spaghetti code, which is completely illegible.
In rare cases , its use makes it possible to bring readability and/or optimization to your
program (error management for example).
As always, a justification will be systematically requested.
16
A-ADVANCED
______ _____
+_ _A1-
_ _ CONSTANT
_ _ _ _ _ _ _ _ POINTERS _____
When creating a pointer (when switching from a pointer to a parameter or internal variable of a function),
if the pointed data is not modified by the function, it should be marked as constant (const).
+_ _A2-
_ _ _TYPING
_______ _____
Prefer the most accurate types possible according to the use of the data.
int counter ; /* A2 violation */
unsigned int counter ; /* OK */
unsigned int get_obj_size ( void const * object ) /* A2 violation */
size_t get_obj_size ( void const * object ) /* OK */
17
H-
_ _ _ HEADER
___ FILES _____
+_ _H1-
___CONTENT
_______ _____
• function prototypes,
• type declarations,
• global variable declarations,
• macros,
• static inline functions.
Header files can include other headers (if and only if it is necessary).
+_ _H2-
_ _ _INCLUDE
_ _ _ _ _ _ GUARD
_ _____
+_ _H3-
_ _ _MACROS
_______ _____
18