0% found this document useful (0 votes)
562 views

Epitech C Coding Style

The document describes coding style guidelines for C programs at Epitech. It covers file organization, naming conventions, global scope, functions, and other style rules. The goal is to standardize code writing to facilitate group work, encourage clear and structured code, and make code easier to read, debug, maintain and reuse. Implicit rules not explicitly defined are also expected to be followed.

Uploaded by

Darian Sereno
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
562 views

Epitech C Coding Style

The document describes coding style guidelines for C programs at Epitech. It covers file organization, naming conventions, global scope, functions, and other style rules. The goal is to standardize code writing to facilitate group work, encourage clear and structured code, and make code easier to read, debug, maintain and reuse. Implicit rules not explicitly defined are also expected to be followed.

Uploaded by

Darian Sereno
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

Epitech Documentation

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 organization of the delivery folder,


• the denomination of the identifiers,
• the overall presentation (paragraphs),
• the local presentation (lines),
• source files and headers,
• Makefiles.

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.

There are 3 levels of severity: major , minor and info .

There are many and many ways to produce unclean code.


Even though one cannot mention all of them in this document, they have to be respected.
We call them implicite rules when not explicitly defined in this document.

Implicit rules are considered as infos .

This document is inspired by the Linux Kernel Coding Style , and is freely adapted from
Robert C. Martin’s excellent book Clean Code.

Some tools (such as Editor Config) might simplify the task.

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
____ _____

Sources in a C program should only have extensions .c or .h.

+_ _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 _____

The pre-processor directives should be indented according to the level of indirection.


# ifndef WIN32
# if defined ( __i386__ ) || defined ( __x86_64__ )
size_t PAGE_SIZE = 4096;
# else
# error " Unknown architecture "
# endif
# endif

The L2 rule also applies for pre-processor directives.

4
+_ _G4-
_ _ _GLOBAL
_ _ _ _ _ _VARIABLES
_ _____

Any non-trivial constant should be defined by a constant global variable.

Non-constant global variables should be avoided as much as possible.

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!

const float GOLDEN_RATIO = 1.61803398875; /* OK */

+_ _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.

Be careful not to confuse the different uses of 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!).

A tab represents 1 character, but several columns.

+_ _F4-
_ _ _NUMBER
_ _ _ _ _ _OF
_ LINES _____

The body of a function should be as short as possible.

6
If the body of a function exceeds 20 lines, it probably does too many tasks!

int main ( void ) /* this function is 2 - line - long */


{
printf ( " hello , world \ n " ) ;
return (0) ;
}

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.

Linus Torvalds, Linux Kernel Coding Style

+_ _F5-
_ _ ARGUMENTS
________ _____

The statement of arguments should be in accordance to the ISO/ANSI C syntax.


A function taking no parameters should take void as argument in the function declaration.
phys_addr_t alloc_frame () ; /* F5 violation */
phys_addr_t alloc_frame ( void ) ; /* OK */

A function should not need more than 4 arguments.


Writing variadic functions is allowed, but they should not be used to circumvent the limit of 4 parameters.

Structures should be transmitted as parameters using a pointer, not by copy.


void make_some_coffee ( struct my_struct * board , int i ) /* OK */
{
do_something () ;
}

+_ _F6-
___COMMENTS
_ _ _ _ _ _ _ INSIDE A FUNCTION _____

There should be no comment within a function.


The function should be readable and self-explanatory, without further need for explanations.

The length of a function being inversely proportional to its complexity, a complicated


function should be short ; so a header comment should be enough to explain it.

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 line should correspond to only one statement.


Typical situations to avoid are:

• several assignments on the same line,


• several semi-colons on the same line, used to separate several code sequences,
• a condition and an assignment on the same line.

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
________ _____

Each indentation level must be done by using 4 spaces.


No tabulation may be used for indentation.

+_ _L3-
_ _ SPACES
________ _____

Always place a space after a comma or a keyword (if it has arguments).

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.

return is a keyword but sizeof is a unary operator!

return (1) ; /* L3 violation */


return (1) ; /* OK */
break ; /* OK */
sum = term1 + 2 * term2 ; /* OK */
s = sizeof ( struct file ) ; /* OK */

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.

In the case of a single-line scope, curly brackets are optional.

if ( cond ) { return ( ptr ) ;} /* L1 & L4 violation */


while ( cond ) { /* OK */
do_something () ;
}
if ( cond ) /* L4 violation */
{
...
} else { /* OK */
...
}
if ( cond ) /* OK */
return ( ptr ) ;
int print_env ( void ) /* OK */
{
...
}
int print_env ( void ) { /* L4 violation */
...
}

+_ _L5-
_ _ VARIABLE
_ _ _ _ _ _ _ _DECLARATION _____

Variables should be declared at the beginning of the scope of the function.


The for-loop counters may optionally be declared within the loop.

Nothing prevents you from declaring and assigning a variable on the same line.

Only one variable should be declared per line.


long calculate_gcd ( long a , long b )
{
long biggest , smallest ; /* L5 violation */

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 ) ;
}

int main ( void )


{
int forty_two = 42; /* OK */
int max = 12; /* OK */

for ( int i = 0; i < max ; i ++) /* OK */


calculate_pgcd ( forty_two , max ) ;
return (0) ;
}

+_ _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 ;
};

struct trashy { /* V2 violation */


struct person player ;
unsigned int width ;
unsigned int length ;
unsigned int score ;
int i ;
};

+_ _V3-
_ _ _POINTERS
_______ _____

The pointer symbol (*) should be attached to the associated variable, with no spaces.

This rule applies only in the pointer context.

int * a ; /* V3 violation */
int * a ; /* OK */

12
int a = 3 * b ; /* OK */
int strlen ( char const * str ) ; /* OK */

13
C-_ _CONTROL
_ ___ STRUCTURE _____

Unless otherwise specified, all control structures are allowed.

+_ _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).

Nested conditonal branchings with a depth of 3 or more should be avoided.

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 (...)

while (....) /* C1 violation */


for (...)
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.

You should never use nested or chained ternaries.


Ternaries should not be used to control program flow.

parity_t year_parity = ( year % 2 == 0) ? EVEN : ODD ; /* OK */


return ( a > 0 ? a : 0) ; /* OK */
int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8; /* C2 violation */
already_checked ? go_there () : check () ; /* C2 violation */

+_ _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 */

ptrdiff_t, uint8_t, int32_t,. . .

17
H-
_ _ _ HEADER
___ FILES _____

+_ _H1-
___CONTENT
_______ _____

Header files should contain only:

• function prototypes,
• type declarations,
• global variable declarations,
• macros,
• static inline functions.

All these elements should be found only in header files.

Header files can include other headers (if and only if it is necessary).

+_ _H2-
_ _ _INCLUDE
_ _ _ _ _ _ GUARD
_ _____

Headers should be protected from double inclusion.


The method and the conventions used are left free.

+_ _H3-
_ _ _MACROS
_______ _____

Macros should not be used for constants


Macros should match only one statement.
# define PI 3. 14 15 926 53 58 97 932 38 46 /* H3 violation */
const float PI = 3 .1 4 15 9 26 53 5 89 7 93 23 8 46 ; /* OK */
# define LOOP_COUNTER 0 /* H3 violation */
# define DELTA (a , b , c ) (( b ) * ( b ) - 4 * ( a ) * ( c ) ) /* OK */
# define PRINT_NEXT ( num ) { num ++; printf ( " % d " , num ) ;} /* H3 violation */

18

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy