Need help with 42_CheatSheet?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

173 Stars 26 Forks 38 Commits 1 Opened issues


Also referred to as "The C Man"

Services available


Need anything else?

Contributors list

42 School Cheat Sheet by agavrel

:two_hearts: Intended for 42 alumni, current students and candidates

Truth can only be found in one place: the codeRobert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship

Table of Content

NB: Use CTRL + F or Command + F to quickly look for keywords.

About 42 School

0x00 ~ What is 42 School

42 is more than just a disruptive educational model and coding school. What makes us unique and a major player in the tech world are the defining characteristics of the 42 culture. Every element of 42 shows our culture, from the students, to the curriculum structure and content, to the $0 tuition and innovative admissions process.

That's right, the school is FREE, originally funded and founded in Paris by generous philanthropist billionaire Xaviel Niel.

I'm not unusual; it's the others who are strangeXavier Niel

The name of the school, "42", is a tribute to The Hitchhiker's Guide to the Galaxy, a comedy science fiction series created by Douglas Adams.

42, or The Answer to the Ultimate Question of Life, The Universe, and Everything

There are no teachers but a pedagogic team that ensure that students do not harm the material and provide a cursus syllabus to follow. What is learned is hence mainly achieved through peer-to-peer project review and RTFM.

RTFM meme

Most of the entrance exam and early cursus is done in C language.

Nevertheless, C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.Brian W. Kernighan, The C Programming Language

C is the most pedagogic programming language you can learn as it allows to understand the basis of programming from simple concepts like conditions {if, elseif, else}, loops {while, do while, for}, write system calls and pointers to more advanced one like function pointers and memory allocation.

Later on you can specialize in other languages: Python will fit data scientists and devops, javascript for frontend developers and C# for those looking for a career in finance.

When you say 'I wrote a program that crashed Windows,' people just stare at you blankly and say 'Hey, I got those with the system, for free.'Linus Torvalds

You will learn how to do what Muggles were only able to do accidentally.

0x01 ~ For Candidates: About the "Piscine"

If you're going through hell, keep going.Winston Churchill

The piscine is the entrance exam that consists of 4 weeks fully dedicated to coding, solving exercises and submitting solo and group projects to peer review.

It does not matter if you fail a project, an exam or a day as long as you keep striving. Someone who has never been interested before in Computer Science would never be able to complete everything in time, yet he will not prevent from being successful.

:coffee: My guess on the success criteria

  • 0x00 Come as you are ... or forget this bullshit and prepare a little bit with subjects on github, courtesy of my friend binary hacker.

  • 0x01 Prepare to nail the exams on the 4 exams session, knowing that the 3 firsts exams are limited in term of how far you can go and it is not a big deal to miss the first 3 exams as the most important is IMHO the maximum level you can reach. Succeeding the first 4 exercises (36 pts) should be enough to make sure you quality.

  • 0x02 Get an acceptable percentage of review from peers (probably 80% is enough, but you would get 90 to 97% if you are nice). Don't be too nice, but don't be a dick with vim .swp files and .DS_Store.

.DS_Store – The name of a file in the Apple OS X operating system for storing custom attributes of a folder such as the position of icons or the choice of a background image. These files are created when you manipulate your files with the Finder GUI.

  • 0x03 The logging time has no or very little influence, I know it as a fact for seeing people constantly logged in (but slacking) failing the piscine and students barely present being accepted. However the more time you spend in 42 school will certainly directly influence your skills and positively impact other related topics

  • 0x04 It is strongly recommended to succeed at least one group project, especially the first one that is really easy.

  • 0x05 There is a special and unique achievement awarded to the most helpful/smart student. This achievement does not show up on the student profile until he asks for it.

  • 0x06 Be aware of the different rules : Many things are forbidden like declaring and assigning a variable in the same line, using printf or using for loops. The daily assignment must be pushed on git before Day + 1 at 11pm42.

  • 0x07 [Boys Only] Don't waste time flirting : For some who have been living in the basement of their parents' house for years it is a good opportunity to see what a girl looks like in real life. Nevertheless, you have to under that 1/this is not the right time and place to do so.

  • 0x08 You can sleep in the school during the selection - I recommended you to not do it, you will have very poor sleep. - If you still go for it here is a list of essential items you should bring: a toothpaste, a toothbrush, a soap and a towel on top of your phone, charger and mattress. Oh and a credit card also, unless you prefer to bring 10kg of cookies

:star: List of Essential Items

Towels are extremely useful for cleaning up messes and drying off your body. You can set it on fire as a weapon, chase off enemies, and use it as a distress signal. Life is messy and sometimes dangerous. Space is even messier and more dangerous. Be like Arthur Dent and keep up with your towel17 Life Lessons From HITCHHIKER’S GUIDE Hero Arthur Dent

:sleepingbed: Mattress or equivalent and Pillow
plug: Phone charger
:iphone: Phone
:droplet: Toothpaste and Toothbrush
:bathtub: Soap and 2-4 Towels
:moneymouthface: Credit Card
:heart: Kleenex

0x02 ~ Coding simple C programs

시작이 반이다The beginning is half of the way (Korean proverb)

First by installing a C compiler on your computer

  • On Windows it is a bit tricky, you will have to install Mingw
  • On Linux it is pretty straightforward since it is only installed and if not
    will make it easy.
  • On MAC it is not much more difficult, google how to do it.

C Data Types

I will only list the main ones

|Data Type|Bytes|Description| |-|-|-| |char|1|Used for text |bool|1|Used to return true or false, you will need the header |short|2|Half the size of an integer, used to optimize memory |int|4|Loop Counter, operations on integers |long|8|Twice the size of an integer, used when overflow is a problem |float|4|Used for computer graphics |double|8|Used for computer graphics, more precised than float but takes more memory |unsigned|.|Apply to char, short, int and long, means than it cannot have negative values

You should then try to recode basic C functions


In computer science, a pointer is a programming language object that stores a memory address.


int main(void) { int a = 5; // declaring an integer variable and assigning the value of 5 int *ptr; // declaring a pointer to integer int b; // declaring an integer variable

ptr = &a;   // pointer ptr points to what is stored at the memory address of variable a
b = a;      // b will take the value and not the address

a = 42;     // b is still equal to 5, but ptr will return 42, which is the value now stored at a's location;

printf("a's value: %d, a's address: %p\n", a, &a);
printf("ptr's value: %d, ptr's address: %p\n", *ptr, ptr); 
printf("b's value: %d, b's address %p\n", b, &b);

return 0;

} </stdio.h>

Note that on the second printf you will get the same as for a, notice that you have to dereference the pointer with * to get the value, and using the pointer alone (ptr) will give you the memory address.


A minimalist c program that will puzzle beginners, write it in a file named a.c and create a.out with

gcc a.c && ./a.out

The following program will print a char by making use of write


void ft_putchar(char c) // void because the function does not return any value, it writes directly, char is the type of the variable c that is given as parameter to the function ft_putchar by the main function. { write(1, &c, 1); // ssize_t write(int fd, const void *buf, size_t count); or in human language: write count letters of buf (which is a pointer) to fd (if fd = 1 this is your terminal, stdout) }

int main(void) { ft_putchar(42); // will print a star // ft_putchar(42 + '0'); // will only print 4 // ft_putchar("4"); // will not work, you are using " instead of ', so C language think it is a char array. return 0; } </unistd.h>

Once you understand well how to print a character, you should try to return the length of many together (it is called a string)



int ft_strlen(char *str) { int i = 0; // set variable i to 0 while (str[i] != '\0') // while the char array does not reach a NULL character i++; // increment i, equivalent of i = i + 1;

return i;                   // return i variable to the caller function


int main(void) { int i = ft_strlen("Duck Tales"); // declare i, call the function ft_strlen, and assign its output to i printf("%d", i); // remember that it is forbidden to submit a function with printf during the Piscine return 0; } </unistd.h>

NB: remember that it is forbidden to submit a function with printf during the Piscine


Then print a whole string by recoding the libc function 'puts': ```c

include // header for puts

int main(void) { puts("Duck Tales"); return 0; } ```

This can be achieve by using and index that starts on the first character and is progressively incremented until NULL as string are NULL terminated: ```c


void ft_putstr(char *str) { int i = 0;

while(str[i] != '\0')
    write(1, &str[i++], 1);

} ```

Along with the main function slightly modified to make use of your code:

int main(void) {
    ft_putstr("Duck Tales");
    return 0;

You can also use only the pointer since you do not care of the return value (the function type being void) ```c


void ft_putstr(char str) { while(str) write(1, s++, 1); } ```

Or even use the length of the string to print the whole string at once, hence avoiding many system calls (write) that are costly for the program execution:

void    ft_putstr(char *str) {
    write(1, str, ft_strlen(str));

NB: You have to include ft_strlen in the same file AND above the function to make it work.

Next you should study the different concepts in programming, especially spend time understanding the different C data types, the concept of pointers and arrays, because it is what you have been using up to now and it will only get more complicated.

0x03 ~ 42 Projects Guides

Do what you think is interesting, do something that you think is fun and worthwhile, because otherwise you won’t do it well anyway.Brian W. Kernighan

|Name|Track|Hashtags|What you will learn| |-|-|-|-| |Fillit|General|Architecture, Parsing, Algo|Description from a student| |Printf|Algorithm|Architecture, Parsing, utf-8|UTF-8 Conversion table
Variadic Function| |Filler|Algorithm|Parsing, Algo, Bot|42 forums have good threads on this project| |Lem-In|Algorithm|Parsing, Algo, Chained-Lists|Dijkstra's algorithm| |Corewar|Algorithm|Architecture, parsing, disassembler, virus, VM|About the original Game| |LS|System|Parsing, Recursion, Chained-Lists|The Good Old Manual| |Minishell|System|Environment Variables, Shell|Bourne Shell| |Malloc|System|Algo, Memory, HashCollision|The Good Old Manual| |FDF|Computer Graphics|Parsing, Creativity|Bresenham's line algorithm, Use of Graphics Library, Trigonometry, Rotations, 3D Projection, ARGB Color Space| |Fractol|Computer Graphics|Fractals, Mathematics, ARGB, HUV|Mandelbrot Set| |Cube3d - Wolf3d|Computer Graphics|Ray Casting, Rotation|About the original Wolfenstein 3d| |NmOtool|System|Symbol Table, .dll .so|Implement List the symbols in a .so file |LibftAsm|System|x86 Assembly Instructions|Refer to the Intel Bible |RT|Computer Graphics|Ray Tracing|Create a Scene of enlightened polygons |Scop|Computer Graphics|Shading|Create a Shader |Particles System|Computer Graphics|Graphics Effects|simulate certain kinds of "fuzzy" phenomena

0x04 ~ Choosing your Path

Never give up on something that you can't go a day without thinking aboutWinston Churchill

How to choose your specialization

There are currently 4 main branches: Infographics, Algorithms, System and Web. All branchs are interesting and you should try to explore each branch's initial project: * If you are aiming to work in the video game industry and like Mathematics then you should go for Infographics. Remember that this path is tough and not necessarily as rewarding as the other ones, but you will have the luxury to work in the video game industry. * Algorithm branch is/was mainly based on flawless parsing and not so much on algorithm quality. Fortunately with the nomination of Benny as the head of the Pedagogy there will be more efforts to reward smart algorithms. Algorithms is the best one if you want to join a prestigious company like Google * System is the best for those who like security, network and how computers truly work since you will have to ultimately recode your own operating system. * Web is good for those who like to build websites, perhaps mobile app as well (react native) and want to become a freelancer.

0x05 ~ Swindle the norminette - truander la norme

While loops

Only 25 lines ? No problem: ```c int draw_lines(int len) { // NB: len is positive or equal to 0 int i;

i = 0;
while (i < len)
    puts("Looping"); // NB: you will have to use your own function, ft_putstr, of course

} ``` Originally 9 lines

int draw_lines(int len) {
    int i;

i = -1;
while (++i &lt; len &amp;&amp; puts("Looping"))


Now 5 lines

int draw_lines(int len) {
    while (--len >= 0 && puts("Looping")) // it works
        draw_line(len); // NB: make sure that drawing backward does not impact algo

2 lines

int draw_lines(int len, int i) { // If you really need to call from 0 to len then you can also have i passed as a parameter = -1
    while (++i < len && puts("Looping"))

2 lines, with prototype modification (ugly)

If brackets

if (true)

5 lines

if (true)
if (true)

4 lines

NB: Beware of these tricks, it could potentially make your program less efficient. In the above example you use two branching instructions - if - instead of one and in the while example the -1 initialization and puts inside the while hinder readability

Write colorful usage

int usage(void)
    static char usage_str[] =

"Simulation of the philosopher.\n\n"
GREEN"philo_one "RESET
"number_of_philosopher time_to_die time_to_eat "
"time_to_sleep [number_of_time_each_philosophers_must_eat]\n\n"
"All args must be positive integer\n";
ft_putstr_fd(usage_str, 1);
return (1);


Function Pointers

void            listen_keystroke(t_dlist **lst)
    char        buffer[8];
    int         el;
    static void (*f[])(t_dlist **lst) = { lst_validate, lst_del_one,
        lst_del_one, lst_move_left, lst_move_right, lst_move_up,
        lst_move_down, lst_select, lst_esc, lst_void_ret};

ft_memset(buffer, 0, 8);
while (read(0, buffer, 8) != -1)
    el = ft_chrmatch(buffer);
    render(find_first(lst), 0);
    ft_memset(buffer, 0, 8);


0x06 ~ Impossible is not C

Negative index Array

#include  // INT_MAX
#include   // printf

int main(void) { int x[2001]; int *y = &x[1000];

y[-10] = 5;
printf("%d\n", y[-10]);

} </stdio.h></limits.h>

It's just a pointer game

Did you know ? Instead of writing array[index], you can write index[array]: ```c int ft_strlen(char *str) { int i = 0; while (i[str]) ++i;

return i;

} ```

Because this is understood by the compiler as pointer arithmetic: ```c int ft_strlen(char str) { int i = 0; while ((str+i)) ++i;

return i;

} ```

Get function name, filename or even line number

macros can be very helpful to display meaningful error messages for both users and developers:
#include     // bool
#include      // write
#include      // malloc
#include      // strlen
#include      // va_list

bool ft_error_va(char *errmsg, ...) { va_list args; char *arg = errmsg;

write(2, errmsg, strlen(errmsg));
va_start(args, errmsg);
while (arg = va_arg(args, char*)) {
    write(2, arg, strlen(arg));
write(2, "\n", 1);
return false;


char *ft_itoa(int n);

bool ft_error(char *errmsg, char *file, const char *function, int line) { return ft_error_va(errmsg, "File: ", FILE, ", in function ",
(char *)function, ", line ", ft_itoa(line), NULL); }

bool dummy_function(void) { if (3 != 2) return ft_error("Error with 3 != 2: ", FILE, FUNCTION, LINE); }

int main(void) { if (!dummy_function()) return 1; return 0; }

char *ft_itoa(int n) { char *s; long tmp; int length;

tmp = n;
length = (n &lt;= 0 ? 2 : 1);
while (n &amp;&amp; ++length)
    n /= 10;
if (!(s = (char *)malloc(sizeof(char) * length)))
    return (NULL);
s[--length] = '\0';
if (tmp &lt;= 0)
    s[0] = (tmp &lt; 0 ? '-' : '0');
while (tmp)
    s[--length] = (tmp &lt; 0 ? -tmp : tmp) % 10 + '0';
    tmp /= 10;
return (s);

} </stdarg.h></string.h></stdlib.h></unistd.h></stdbool.h>

If you don't know what variadic functions are,

, you can check my implementation of printf

Setting values of a struct to 0 without using memset or bzero

You can use either:

t_mystruct mystruct = {};

or, to comply with 42 Norminette that forbid declaration and assignation on the same row:

t_mystruct mystruct;

:fire: Common Beginner Mistakes

Experience is the name everyone gives to their mistakesOscar Wilde

0x00 ~ Array overflow

In C the index of an array starts at 0. Because C does not perform boundary checking when using arrays, if you access outside the bounds of a stack based array it will just access another part of already allocated stack space, like in this example:


void somefunction3(void) { int a[5] = {1,3,5,7,9}; printf("%d\n", a[5]); } </stdio.h>

In this example, 5 is the size of the array and if you try to access it it will overflow. Remember that the maximum array index you can ever access is its size minus 1.

I would suggest to use as much as possible a const : ```c


void somefunction3(void) { const int len = 5; int a[len] = {1,3,5,7,9}; for (int i = 0; i < len; i++) // safe printf("%d\n", a[i]); } ```

0x01 ~ Segmentation Fault

There are two ways to write error-free programs; only the third one worksAlan J. Perlis

Many potential reasons for this...

Loop segfault

One common mistake is that you had declared a loop and either:

Forgot to increment the counter

int i = 0;

while (i < 10) { write(1, &i + '0', 1); // but where is i++ ? }

Correct way

int i = 0;

while (i < 10) { write(1, &i + '0', 1); i++; }

Forgot the exit condition:

int somevariable = 0;
while (42) // always True ! You will be 42 for life ;)
    // call to some stuff that never succeed to set someVariable to 1;
    if (somevariable == 1) // make sure that somevariable will equal 1 at some point.
        break ;

Used an assignation = instead of a boolean expression != == <= >=


int main(void) { unsigned int x = 10;

while (--x != 0)
    printf("0 0 0 1 0 1 0 1 0 ");
    if (x = 1) {            // oopsie !!
        printf("* ");
return 0;

} </stdio.h>

PS: will you be able to fix this code ?

Also classic with lists: you have a loop and its crucial condition that allows the function to return, but used an assignation instead of comparison ```c int i = 0;

while (list) { if (list = NULL) // You want to use if (list == NULL) return i; i++; list=list->next; } return -1; // will always return -1 ```

Quizz: What will print this loop ?

unsigned char c = 0;

while (c < 150) { write(1, &c, 1); c++; }

Talk is cheap. Show me the codeLinus Torvalds

Accessing the next link in a chained-list without checking the current one

Another example with linked-lists ```c typedef struct slist { void *data; tlist *next; } t_list;

/* ** function to go 2 links further in a chained-list */

void somefunction(t_list *list) { if (list->next != NULL) { list = list->next->next; } } ```

if the current link of list is null you will get a segfault. The correct way is to always check the current link before the next one:

void somefunction(t_list *list)
    if (list && list->next) // if both list and list->next exist
        list = list->next->next;

Accessing an index in a loop for program with either graphics or a board game

int somefunction(int y_max, int x_max, int array[y_max][x_max]);
    int y;
    int x;

y  = 0;
while (y &lt; y_max)
    x = 0;
    while (x &lt; x_max)
        if (array[y][x-1] &gt; array[y][x]) // don't you see there is a problem ?
            array[y][x] = array[y][x-1];
        if (array[y+1][x] &gt; array[y][x]) // don't you see there is another problem ?
            array[y][x] = array[y+1][x];



These lines should be corrected the following way:

if (x > 0 && array[y][x-1] > array[y][x])
if (y < y_max - 1 && array[y+1][x] > array[y][x]) // strictly inferior to last possible index which is y_max - 1,
// you may also write y <= y_max - 2

You may also notice that we can even do better by changing the starting value of x or the exit condition of the y loop in the case that we were to check only one of the two if conditions.

x = 1;
while (y < y_max - 1)

Another example ```c int main(void) { const int xmax = 3; const int ymax = 3; int a[ymax][xmax];

for (int y = 0; y < y_max; y++)
    for (int x = 0; x < x_max; x++)
        a[y+6][x] = x + y;

} ```

0x02 ~ Bus error

Occur when your processor cannot even attempt the memory access requested, like trying to access an address that does not satisfy its alignment requirements. ```c int main(void) { const int xmax = 3; const int ymax = 3; int a[ymax][xmax];

for (int y = 0; y < y_max; y++)
    for (int x = 0; x < x_max; x++)
        a[y][x] = a[x] + a[y];

} ```

0x03 ~ Stack smashing

See below in the recommended books the one by Aleph One, how you can make use of such "error" ```c int main(void) { const int xmax = 3; const int ymax = 3; int a[ymax][xmax];

for (int y = 0; y < y_max; y++)
    for (int x = 0; x < x_max; x++)
        a[y][x] = x + y;

for (int y = 0; y < y_max; y++) { for (int x = 0; x < x_max; x++) { a[y+6][x] += a[y][x]; } }

} ```

0x04 ~ Modifying value of a local variable given as function parameter

Local variable value are allocated on the stack, which is cleaned once you exit the function.

Useless variable change

void increment_a(int a)
    a++; // it will have no effect

int solve(void) { int a = 5;



Useful variable change

Hence if you want to modify a value you either have to use a pointer to the memory address: ```c void increment_a(int *a) { *a++; }

int solve(void) { int a = 5;


} ```

or return the local value: ```c int increment_a(int a) { return a + 1; }

int solve(void) { int a = 5;

a = increment_a(a);

} ```

0x05 ~ Unprotected malloc

Do NOT leave a malloc unprotected: ```c int allocate_memory(void) { int *matrix;

matrix = malloc(sizeof(int) * 9))

return matrix;


int somefunction(void) { int *matrix;

matrix = allocate_memory();

} ```

Protect both the malloc and its return value: It is not good enough to protect the malloc in the callee function (the function called) if the returned value is not also protected in the caller function (the function 'above') ```c int allocate_memory(void) { int *matrix;

if (!(matrix = malloc(sizeof(int) * 9))) // this is short for matrix = malloc(sizeof(int) * 9; if (matrix == NULL)
    return NULL;   // the malloc is now protected,

return matrix;


int somefunction(void) { int *matrix;

if ((matrix = allocate_memory()) == NULL) // the return value is also protected
        exit(); // note that often you can't or don't want to use exit() and will need to return 0 along all the functions up to the main function.

} ```

0x06 ~ Freeing memory that has already been fred

In the previous example, if you don't need the variable matrix anymore you can free it.

However do not attempt to free twice or to free a stack based variable: ```c int main(void) { int *matrix;

if (!(matrix = malloc(sizeof(int) * 9)))
    return 1; // NB: exceptionnally return 1 in the main, it means that an error occured
free(matrix); // OK
free(matrix) // Not OK

return 0; // return 0, the program run without error

} ```

0x07 ~ Do Not use global variables

"Theory and practice sometimes clash. And when that happens, theory loses.
Every single time." ― Linus Torvalds

Global variables are forbidden in 42 School except for a few exceptions, see this interesting article: Are Global Variables Bad However many students, me including, found a way to circumvent this interdiction: you first declare a structure in the header that will contain all our variables:

"Don’t comment bad code—rewrite it." ― Brian W. Kernighan, The Elements of Programming Style

typedef struct s_env
    int a;
    int b;
    int c[4];
    // ... other variables you may need
}           t_env;

And then using it the following way in the program: ```c void somefunction2(t_env *env) { env->b = 2; }

void somefunction(t_env *env) { env->a = 1;



int main(void) { t_env env;


printf("%d\n", env.a); printf("%d\n", env.b);

} ```

This is "legal" in 42 (it is not a global variable, it is a structure passed along functions), it "works", but it is a very poor architecture choice. It is okay for beginner to do this but as your skill grows you should find more clever ways to architecture your programs.

0x08 ~ Variable Length Arrays

Waiter! There's a VLA in my C!

The following example is a VLA and this is bad for many reasons, the most critical being that the memory is allocated on the stack which has a limited size.

int somefunction(int y, int x, int array[y][x]);
My peer reviewer: "wow your filler run so fast!" Me: "really ?" (how to tell them that it was not compliant with the norm? :D)

0x09 ~ Using ft_ prefix for all functions

ft_ should only be added to functions you want to re-use through different projects (and add to your personal library, the libft project) not for specific program functions.

0x0A ~ Usage of Sequence Point


int main() { int i = 0; i = (i++); write(1, &i + '0', 1);

return 0;

} </unistd.h>

Guess what will be printed.

0x0B ~ Assignment of read-only location

int main()
    const char s[20] = "hello world";
    *s = 'a';
    s[0] = 'b';

return 0;


You cannot change what you have declared as const.

OXOC ~ Carefully use define preprocessor macros


#define MAX(a,b) a > b ? a : b

int main(void) { int a = 5; int b = 42; int c = 40 + MAX(a,b);

printf("%d\n", c);
return 0;

} </stdio.h>

This will return 5, becaure the compiler understand it as :

int main(void) {
    int a = 5;
    int b = 42;
    int c = 40 + 5 > 42 ? 5 : 42; // if 47 > 42 then c = a (5) , else c = b (42);

The correct usage is to always encapsulate your

with brackets to make sure it works as intended: ```c

define MAX(a,b) (a > b ? a : b)

That said you should avoid using macros who act like functions in the first place. Also note that you should always capitalize macro names and const variables, it is a convention.

0x0D ~ Comparing float and double

#include <stdio.h>

int main(void) {
    double d = 1.1;
    float f = 1.1;

    if (f != d)
        puts("float and double are different\n");
    if (f != 1.1)
        puts("Do not compare a float to an integer value\n");
    if (d == 1.1)
        puts("But that's okay for a double\n");
    if (f == 1.1f)  // note the extra 'f' at the end
        puts("This is how you compare a float to a float value\n");

    return 0;
<p>They are represented differently. If you want to learn more about how they work take a look at <a href="">wikipedia</a> or wach below video.  </p>

<p><a href="" target="_blank"><img src="" alt="Floating Point Numbers" width="240" height="180" border="10"></a></p>


<h2>0x0E ~ Wrong usage of pointers</h2>

<p>Pointers are the memory location of the value of this variable</p>

<p>An example with ft_swap</p>

<h3>The wrong way to use pointers</h3>
<pre class="language-c">void ft_swap(int *a, int *b)
    int *tmp;

    *tmp = *a;
    *a = *b;
    *b = *tmp;
<p>This will segfault, because you declared tmp as a pointer, but what you want is tmp to store the value of the memory address of a.</p>

<h3>The correct way to use pointers</h3>
<pre class="language-c">void ft_swap(int *a, int *b)
    int tmp;

    tmp = *a;
    *a = *b;
    *b = tmp;
<h3>Swapping without using another variable</h3>
<pre class="language-c">=void ft_swap(int *a, int *b)
    *a ^= *b;       // (1) a = a ^ b
    *b ^= *a;       // (2) b = b ^ (a ^ b) = a
    *a ^= *b;       // (3) a = (a ^ b) ^ a  = b  // a was set to a^b (1) and b became a (2)

<p><strong>NB: if you xor a number by itself you set it to 0. <pre>a ^= a;</pre> is equivalent to <pre>a = 0;</pre></strong><br>
<em>If you like it you can <a href="">learn more about bitwise operations here</a></em></p>

<h3>Main to test above functions</h3>
<pre class="language-c">#include <stdio.h>

int main(void)
    int a = 5;
    int b = 42;

    printf("a: %d \t b: %d\n", a, b);
    ft_swap(&amp;a, &amp;b);
    printf("a: %d \t b: %d\n", a, b);
    return 0;

<h2>0x0F ~ Undefined Behavior</h2>

<p>Undefined behavior means that the result is <strong>as much unpredictable as a <a href="">pangolin</a> sneezing in some faraway country</strong>. <em>You don't want to have your program depending on it.</em></p>
<pre class="language-c">#include <stdio.h>

char omg(char i) {
return ++i + ++i + ++i + ++i + ++i + ++i + ++i \
    + ++i + ++i + ++i + ++i + ++i + ++i + ++i \
    + ++i + ++i + ++i + ++i + ++i + ++i + ++i \
    + ++i + ++i + ++i + ++i + ++i + ++i + ++i \
    + ++i + ++i + ++i + ++i + ++i + ++i + ++i \
    + ++i + ++i + ++i + ++i + ++i + ++i + ++i \
    + ++i + ++i + ++i + ++i + ++i + ++i + ++i \
    + ++i + ++i + ++i + ++i + ++i + ++i -5;

int main(int argc, char **argv) {
    unsigned char i = omg(i);

    if (i++ &gt; 254)
        printf("%d\n", ++i);
<p><em>Try guessing the output</em></p>


<h2>0x10 ~ Operator Precedence</h2>

<p>Often you may write some code like:
return !(a &amp; b &lt;&lt; 8);

<p>This is bad because you ignore the rule of operator precedences, and should have written the return as:
return !(a &amp; (b &lt;&lt; 8));

<p>Another example with pointers:

<p>Below you will find the full table of <a href="">operator precedence</a>:</p>

<p>Precedence | Operator | Description | Associativity
1|++ --|    Suffix/postfix increment and decrement|Left-to-right
1|()|Function call|Left-to-right
1|[]|Array subscripting|Left-to-right
1|.|Structure and union member access|Left-to-right
1|-&gt;|Structure and union member access through pointer|Left-to-right
1|(type){list}|Compound literal(C99)|Left-to-right
2|++ --|Prefix increment and decrement|Right-to-left
2|+ -|  Unary plus and minus|Right-to-left
2|! ~|  Logical NOT and bitwise NOT|Right-to-left
2|<em>|    Indirection (dereference)|Right-to-left
2|&amp;|    Address-of|Right-to-left
2|_Alignof|Alignment requirement(C11)|Right-to-left
3|</em> / %||Left-to-right
4|+ -||Left-to-right
5|&lt;&lt; &gt;&gt;||Left-to-right
6|&lt; &lt;=||Left-to-right
7|&gt; &gt;=||Left-to-right
8|== !=||Left-to-right
10||Bitwise OR|Left-to-right
11||Logical AND|Left-to-right
12||||logical OR|Left-to-right
13|?:|Ternary conditional|Right-to-left
14| =|Assigment|Right-to-left
14|+= -=|Assigment by sum and difference|Right-to-left
14|*= /= %=|Assigment by product, quotient and remainder|Right-to-left
14|&lt;&lt;= &gt;&gt;=|Assigment by bitwise left and right shift|Right-to-left
14|&amp;= ^= |=|Assigment by bitwise AND, XOR and OR|Right-to-left


<h1>:snowflake: Clean Code</h1>

<p>"You are reading this book for two reasons. First, you are a programmer. Second, you want to be a better programmer. Good. We need better programmers." ― <em>Robert C. Martin in Clean Code</em></p>

<p>Now some guidelines that should hopefully help your coding style</p>


<h2>0x00 ~ Meaningful and Explicit Names</h2>

<p>“Don’t comment bad code, rewrite it.” Brian W. Kernighan, The Elements of Programming Style</p>

<p>I once met a developer who was using hp and mp instead of x and y for coordinates.<br>
While being a very good reference to <a href="">JRPG</a>... it is totally out of question to code like this.
The function name should always be:
* In English, forget about chauvinism!
* At least 5 letters. It is okay to have shorter exceptionally for well-known variables like int index -&gt; int i, temporary -&gt; tmp and pointer -&gt; ptr.
* Self-explanatory: build<em>graph instead of graph or build</em>it
* For long name use either camel case (saveClientConfig) or snake case (save<em>client</em>config) and stick to one style.</p>

<h3>Writing a function check if a file exist</h3>
<pre class="language-c">#include <sys>   // stat
#include <stdbool.h>    // bool type
#include <stdio.h>      // printf

bool    file_exist (char *filename) // Always use bool for Manichean functions
  struct stat   buffer;

  return !stat(filename, &amp;buffer);

int     main(int ac, char **av) {
    if (ac != 2)
        return 1;

    if (file_exist("a.out"))
        printf("%s exists\n", av[1]);
        printf("%s does not exist\n", av[1]);

    return 0;

<h2>0x01 ~ Write short functions</h2>

<p>"FUNCTIONS SHOULD DO ONE THING. THEY SHOULD DO IT WELL. THEY SHOULD DO IT ONLY." ― <em>Robert C. Martin in Clean Code (p35)</em></p>

<p><strong>42 has a rigid but fair rule: limits every functions to 25 lines.</strong>  </p>

<p><em>Let's see a case study with a function to get lower case (from 'A' to 'a') for a given character</em></p>

<p><strong>0b001 Function done by a 42 'Piscineux' (AKA it works):</strong>
char    to_lower_by_piscineux(char c) {
    if (c &gt;= 'A' &amp;&amp; c &lt;= 'Z')
        return c - 'A' + 'a';
    else if (c &gt;= 'a' &amp;&amp; c &lt;= 'a')  // useless else if, since both else if and else return the same value
        return c;
        return c;

<p><strong>0b010 Good 42 Student who read GNU C library's tolower's man and read <pre>int tolower(int c)</pre> (prototype):</strong>
int     to_lower_by_student(int c) {
    if (c &gt;= 'A' &amp;&amp; c &lt;= 'Z')
        return c - 'A' + 'a';
    else            // NB: Don't keep this extra "else" as there is no code executed after the return statement
        return c;

<p><strong>0b011 However you could save memory by using only 1 byte (char) instead of 4 (int) since ASCII values range from 0 to 127 as demonstrated by Steve Maguire in "Writing Solid Code" (p101):</strong>
char    to_lower_by_smaguire(char c) {
    if (c &gt;= 'A' &amp;&amp; c &lt;= 'Z')
        return (c + 'a' - 'A');
    return (c);

<p><strong>0b100 My own version: <a href="">making use of the ASCII table</a> and apply the Do Only One Thing principle:</strong>

<h1>include <stdbool.h>    // bool type</stdbool.h>

<p>bool    is<em>upper</em>case(int c) {
    return ((unsigned int)(c - 'A') &lt;= ('Z' - 'A'));

<p>int     to<em>lower</em>by<em>agavrel(int c) {        // Check ASCII table and you will notice a nice pattern
    return is</em>upper_case(c) ? c | 0b100000 : c;

<p><strong>0b101 You may try above functions with the following main program:</strong>

<h1>include <unistd.h>     // write syscall</unistd.h>

<p>void    putchar_endl(char c) {  // NB: endl stands for endline, '\n'
    write(1, &amp;c, 1);
    write(1, "\n", 1);

<h1>include <ctype.h>      // GNU C Library tolower</ctype.h>

<p>int     main(int ac, char **av) {
    if (ac != 2)
        return 1;</p>
<pre>unsigned char c = *av[1];

return 0;

<p><strong>0b110 Have you tried <a href="">one step closer</a> to the bytecode  ?</strong>
int     to_lower_assembly(int c) {
    __asm__ __volatile__ (R"(
    .intel_syntax noprefix
        mov     eax, %0
        lea     edx, [eax - ('A')]
        or      %0, 0b100000
        cmp     edx, 'Z'-'A'
        cmovb   eax, %0     
    .att_syntax noprefix)"
    :[c]"=r" (c)
    :: "memory");


<h2>0x02 ~ Using structure for basic items</h2>

<p>If you are using coordinates it might be interesting to create a structure 'point' or 'coord'</p>
<pre class="language-c">typedef struct s_point
    int y;
    int x;
}           t_point;

void somefunction(void){
    t_point p;

    p.x = 2;
    p.y = 5;

    //alternatively:  p = {5, 2};

<h2>0x03 ~ Using flags for projects' options</h2>

<p>For each project you will often have to parse flag input. In Linux the flag usually come after a '-' and allow for extra functionalities.
It is quite useful know how to store such critical information into only 4 bytes <em>which is sizeof(integer)</em></p>
<pre class="language-c">static int  ft_strchr_index(char *s, int c)
    int     i;

    i = 0;
    while (s[i])
        if (s[i] == c)
            return (i);
    return (-1);

int         get_flags(char *s, int *flags)
    int     n;

    while (*(++s))
        if ((n = ft_strchr_index("alRrtdG1Ss", *s)) == -1)
            return (0);
        *flags |= (1 &lt;&lt; n);
    return (1);

int         main(int ac, char **av)
    int i;

    int flags = 0;
    i = 0;
    while (++i &lt; ac &amp;&amp; av[i][0] == '-' &amp;&amp; av[i][1])
        if (av[i][1] == '-' &amp;&amp; av[i][2])
            return (i + 1);
        if (!get_flags(av[i], &amp;flags))
            return (-1);
    return (i);
<p>The 'a' flag will be on bit 1, 'l' on bit 2, 'R' on bit 4, 'r' on bit 8 etc.
You can then test if the flag was on by using the following:

<h1>define FLAG_A  0b001</h1>

<h1>define FLAG_L  0b010</h1>

<h1>define FLAG_RR 0b100</h1>

<h1>include <stdio.h></stdio.h>

<p>void    somefunction(int *flags)
    if (flags &amp; FLAG_A)
        printf("Flag a is set!\n");<br>

<p><em>NB: Be very cautious as &amp; and | have lower precedence than relational operators:</em>
if (flags &amp; FLAG_L == MASK) // equivalent to (flags &amp; (FLAG_L == MASK))

<p><em>Correct example:</em>
if ((flags &amp; FLAG_L) == MASK)

<p>You can unset a flag by clearing the corresponding bit the following way:
void    somefunction2(int *flags)
    flags &amp;= ~FLAG_A;

<p><strong>Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live</strong> – <em>John Woods</em></p>

<p>An even more readable and better approach is to declare a struct using bitfield:</p>
<pre class="language-c">struct  flags_t
    int a : 1;
    int b : 1;
    int c : 1;

#include <unistd.h>

int main(void) {
    struct flags_t flags = {0};
    t.a = 1;
    if (t.a)
        write(1, "flag a is set\n", 14);
    return 0;
<p>PS: Of course rename flags' name with more meaningful ones.</p>


<h2>0x04 ~ Using gcc flags for Makefile</h2>

<p><strong>It's funny how the smallest things I've done speak the loudest about me, but I like that</strong> ― <em>Xavier Niel</em></p>
<pre>gcc -Wall -Wextra -Werror -O2
<li>O2 will improve performance  ##Create a new repository on the command line</li>
<li>pedantic is not requested but is a good one to check ISO C compliance</li>

<p>Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.</p>

<p>You can read the details about each flag on <a href="">gccgnu website</a></p>


<h2>0x05 ~ Using preprocessor DEBUG macros</h2>

<p><strong>Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?</strong> ― <em>Brian W. Kernighan</em></p>

<p>You can improve the performance of your program by using what we call preprocessor macros

<h1>include <unistd.h></unistd.h>

<h1>define DEBUG true</h1>

<p>int main(void) {
    if (DEBUG)
        write(1, 42, 1);
    return 0;

As a convention name should be capitalized with '_' to join words

0x06 ~ Branching Optimization

Often you will test that a specific value is reached or that a variable is set using if condition. But the order of the comparisons can improve efficiency of your program.

What would be wrong with the below function? ```c

int countertostar(int a, int b) { while (42) { if (((a + b) & 1) && a == 42) { break; } a |= 1; a *= b; a %= 60; b++; n++; }

return n;

} ```

What is wrong is that the most unlikely condition

a == 42
is tested last, while it should be tested first. The most likely condition, that a + b is odd
(a + b) & 1
should be tested only if a == 42, and since 42 is even, you only need to test if b is odd:
if (a == 42 && (b & 1)) {

#define DEBUG true

int main(void) { int a = 42; if (a && a

0x07 ~ Reserved Keywords


static the function or variable can only be used within its file, it is somewhat similar to the concept of private
inline compiler will attempt to embed the function into the calling code instead of executing an actual call.
const will make the variable immutable
break; continue; will respectively exit from the loop and go to the beginning of the loop

Programmer Tools

0x00 ~ Code Editors

Vim, Code Editor used in 42

VIM is the text editor used in 42. You access a file by using

vim filename
. To exit VIM with elegance vim type
, if you fail to exit VIM you might consider becoming a freelance web developer.

To generate a truly random string, put a web developer in front of Vim and tell them to exit

You can access VIM configuration by typing

vim ~/.vimrc

Below is my configuration ``` set number " Show line number syntax on " Highlight syntax set mouse=r " Enable mouse click, + enable to copy paste without taking line number set cursorline " Enables cursor line position tracking hi Normal guibg=NONE ctermbg=NONE " keep vim transparency highlight CursorLine ctermfg=darkgreen ctermbg=darkgrey cterm=bold " highlight row with foreground background and style as defined "highlight CursorColumn ctermbg=darkgrey " hilight column highlight CursorLineNR ctermfg=red ctermbg=darkblue cterm=bold " Sets the line numbering to red background

set cursorcolumn " Highlight current column set tabstop=4 " set tab to 4 spaces set autoindent " auto indent file on save

set modeline " make vim change in a specific file set modelines=5 ```

Some shortcuts that are very handy:

CTRL+HOME   send you at the beginning of the file
CTRL+END    send you at the end of the file
YY          copy
PP          paste
DD          delete row
D5D         delete 5 rows
w           save file
q           quit file
:vs {file location}     open another file on the side
:ws         save and quit
ZZ          save and quit
:x          save and quit
:q!         quit without change
ZQ          quit without change

Visual Studio Code

I love VIM and it will always be useful to know how to use it, especially now with the "Cloud" being something you might have to access servers who lack code editors with real GUI.

That said If you want to give a try to another editor I would recommend Visual Studio Code.

My settings.json:

    "workbench.colorTheme": "Monokai",
    "glassit-linux.opacity": 93


Good editor also, quite hackable, I have been using it for years but recently switch to VIM & VS Code

0x01 ~ Terminal Bash

Bash is the terminal you will be using

You can create alias by accessing

vim ~/.bashrc
alias ls="ls -la"

PS: Don't create this alias on another's student computer, even thought you might think it is funny, it will wipe out everything:

alias ls="rm -rf ./~"

0x02 ~ Git

Setting up a new Git Repository using CLI

It can be done easily using the following command line:

mkdir $reponame
git init
git add
git commit -m "[INIT] First commit"
git remote add origin [email protected]:agavrel/$reponame.git
git push -u origin master

Change last commit without changing commit message

I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do itBill Gates

It can be done easily using the following command line

git add \
&& git commit --amend --no-edit \
&& git push --force
NB: Beware because it will destroy the previous commit with all what it implies

0x03 ~ Productivity Gains

One of my most productive days was throwing away 1000 lines of codeKen Thompson

Compile and Execute file on changes

Create ou run the following script (necessite to download

sudo apt-get install inotifywait
while inotifywait -e close_write agavrel.s; do \
nasm -f elf64 agavrel.s \
&& gcc agavrel.c agavrel.o -o a.out \
&& ./a.out arg1 arg2 \
; done
Now each time you compile your file you will set the output, very efficient with a transparent editor.

Use the following script and give the .c file as argument:

while inotifywait -e close_write $1; do \
gcc $1 \
&& ./a.out \
; done

Run Commands in Background

You can have multiple processes running in the background at the same time with

after the command.
However the background process will continue to write messages to the terminal from which you invoked the command.

To suppress the stdout and stderr messages use the following syntax:

command > /dev/null 2>&1 &

>/dev/null 2>&1
means redirect

Use the jobs utility to display the status of all stopped and background jobs in the current shell session:

jobs -l
NB: a Job is the process running thanks to the command execution

To bring the job to the foreground use :

fg %ID
NB: you can use
to do the reverse, from foreground to background.

To kill the process use:

kill -9 ID
Obviously replace
in the above examples with the job ID you got from
jobs -l

0x04 ~ Add a a new binary in the PATH environment variable

Example with terraform:

sudo mkdir /opt/terraform
unzip ~/Downloads/ /opt/terraform

add to PATH environment variable:

export PATH="$PATH:/opt/terraform"

then create simlink in /user/bin

cd /usr/bin
sudo ln -s /opt/terraform terraform

Update path for current session

source ~/.profile
source ~/.bashrc

0x05 ~ Computer Graphics Libraries (Ubuntu)

Minilibx Installation


SDL2 Installation



&& make
&& sudo make install
&& sudo apt-get install ibsdl2-dev libsdl2-ttf-dev
&& sudo apt-get libsdl2-image-2.0-0 libsdl2-image-dev

:gem: Curated list of Programming Learning Materials

Only petty thieves would google the following material, adding "torrent" or "pdf" keywords, real Gentlemen would purchase a digital copy

NB: If you want to complain about a copyright enfringment, kindly raise an issue or send me an email and I will remove the offending link

0x00 ~ C Knowledge

C is quirky, flawed, and an enormous successDennis Ritchie, Creator of the C language


How Interesting Author
The C Programming Language 2nd Ed Subsequent Edition :two_hearts: by Brian Kernighan and Dennis Ritchie
Obscure C Features :star::star::star::star::star: by Multun
Characters, Symbols and the UTF-8 Miracle - Computerphile :star::star::star::star: by Tom Scott
Automatic Vectorization :star::star::star::star: by Marchete
Writing Solid Code :star::star::star::star: by Steve Maguire
Fast wc Multithread SIMD :star::star::star::star: by expr-fi
OpenMP Multithreading Programming :star::star::star::star: by Joel Yliluoma
Understanding lvalues and rvalues :star::star::star::star: by Eli Bendersky
The Practice of Programing :star::star::star: by Brian W. Kernighan and Rob Pike
Modern C :star::star::star: by Jens Gustedt
Duff's Device :star::star::star: by Tom Duff
Structure Packing :star::star::star: by Eric S. Raymond
Cello, High Level Programming to C :star::star::star: by Daniel Holden
Are Global Variables Bad :star: StackOverFlow

0x01 ~ Algorithm

When you see a good move, look for a better oneEmanuel Lasker


How Interesting Author
Nailing the Coding Interview :kr: by Antonin Gavrel
A curated list of Awesome Competitive Programming :star::star::star::star: by Inishan (Jasmine Chen)
The Algorithm Design Manual :star::star::star::star: by Steven S. Skiena
Games of Magnus Carlsen and Tactics, 2013 :star::star::star::star: by GM Varuzhan Akobian
A tour of the top 5 sorting algorithms with Python code :star::star: by George Seif

Strategy requires thought, tactics require observationMax Euwe

0x02 ~ Bitwise Manipulations

The word bit is a contraction of binary digit that was coined by the statistician John Tukey in the mid 1940sBrian W. Kernighan, D Is for Digital


How Interesting Author
Hacker's Delight :twohearts: by Henry S. Warren Jr.
Bit Twiddling Hacks :twohearts: by Sean Eron Anderson
De Bruijn Sequence :star::star:

0x03 ~ Network

I would tell you a joke about UDP but I’m afraid you wouldn’t get it


How Interesting Author
Next Generation Kernel Network Tunnel - WireGuard :two_hearts: by JA Donenfeld
Onion Routing :star::star::star::star: by Computerphile
TCP Meltdown :star::star: by Computerphile

0x04 ~ Hacking & Security

Never underestimate the determination of a kid who is time-rich and cash-poorCory Doctorow, Little Brother


How Interesting Author
Smashing The Stack For Fun And Profit :twohearts: by Aleph One
Violent Python - A Cookbook for Hackers, FA, PT and SE :twoheats: by TJ O'Connor
Breaking the x86 Instruction Set :star::star::star::star::star: by Domas
Buffer Overflow, Race Condition, Input Validation, Format String :star::star::star::star: by Wenliang (Kevin) Du
Meltdown :star::star::star::star: by Lipp, Schwarz, Gruss, Prescher, Haas, Mangard, Kocher, Genkin, Yarom, and Hamburg
Basic Linux Privilege Esclation :star::star::star: by g0tmi1k
Network Protocol Fuzzing and Buffer Overflow :star::star::star::star: by Joey Lane
**Secure Programming HOWTO :star::star::star: by David A. Wheeler
Padding the struct :star::star::star: by NCC Group
Efficiently Generating Python Hash Collisions :star::star:
Stochastic Process Wikipedia :star::star:
Gimli: a cross-platform permutation :star::star:
LiveOverflow :star::star:


Forum cracks the vintage passwords of Ken Thompson and other Unix pioneers
Most Common Chess Openings
Kasparov Miniature and Tactics/Endgames | Kids' Class - GM Varuzhan Akobian

When in doubt, use bruteforceKen Thompson

0x05 ~ Computer Graphics

Programming is not a zero-sum game. Teaching something to a fellow programmer doesn't take it away from you. I'm happy to share what I can, because I'm in it for the love of programmingJohn Carmack


How Interesting Author
SDL2 Tutorial :twohearts: by mysterious Lazyfoo
The Book of Shaders :twohearts: by Patricio Gonzalez Vivo & Jen Lowe
Fast Inverse Square Root :two_hearts: attributed to John Carmack (Quake III)
Game Engine Architecture :star::star::star::star::star: by Jason Gregory
Introduction to Computer Graphics :star::star::star::star::star: by Justin Solomon
RayCasting Tutorial + Source Code :star::star::star::star::star: by Lodev
Shaders Programming :star::star::star::star: by Hitesh Sahu
Coding Minecraft in two days (source code)[] :star::star::star::star::star: by Jdah
Moving Frostbite to Physically Based Rendering 3.0 :star::star::star::star:
3d Fractal Flame Wisps :star::star::star: by Yujie Shu
Geometry Caching Optimizations in Halo 5 :star::star::star: by Zabir Hoque and Ben Laidlaw
Physically-Based Shading at Disney :star::star::star: by Brent Burley, Walt Disney Animation Studios
Light and Shadows in Graphics :star::star: by Tom Scott
Screen Space Ambient Occlusion Tutorial :star::star: by Tom Scott
Exponentiation by Squaring :star: Wikipedia

0x06 ~ Computer Vision & AI

It is through science that we prove, but through intuition that we discoverHenri Poincaré


How Interesting Author
OpenCV Tutorial :star::star::star:

0x07 ~ C++ Optimization

C++ is a horrible language. It's made more horrible by the fact that a lot of substandard programmers use it, to the point where it's much much easier to generate total and utter crap with itLinus Torvalds 2007


How Interesting Author
Optimizing software in C++ :twohearts: by Agner Fog
Intel Intrinsics Guide What is it :twohearts: Intel
Software Performance and Indexing :two_hearts: by Daniel Lemire
"Low Latency C++ for Fun and Profit" :star::star::star::star: by Carl Cook
Why I Created C++ :star::star::star: Bjarne Stroustrup
CppCon 2018 “High-Radix Concurrent C++” :star::star::star: Olivier Giroux
C++ Features :star::star::star: by Anthony Calandra

0x08 ~ Assembly Optimization

People say that you should not micro-optimize. But if what you love is micro-optimization... that's what you should doLinus Torvalds


How Interesting Author
Intel® 64 and IA-32 architectures software developer’s manual :twohearts: Intel
Optimizing subroutines in assembly x86 language :twohearts: by Agner Fog
Online Compiler Explorer :star::star::star::star::star: by Godbolt
Online Assembler and Disassembler :star::star::star::star: by Taylor Hornby
A Guide to inline assembly for C and C++ :star::star::star::star: by Salma Elshatanoufy and William O'Farrell
Tips for Golfing in x86/x64 Bytecode :star::star::star: by StackExchange
The Art of Assembly Language :star::star: by Randal Hyde
GDB Tutorial :star::star: by Andrew Gilpin

0x09 ~ Functional Programing by Leonard Marquez

A monad is just a monoid in the category of endofunctors, what's the problem?James Iry


How Interesting Author
Learn You a Haskell for Great Good! :twohearts: by Miran Lipovača
Functors, Applicatives, And Monads In Pictures :twohearts: by Aditya Bhargava
Category Theory course by Bartosz Milewski :star::star::star::star::star: by Bartosz Milewski
Wise Man's Haskell :star::star::star::star: by Andre Popovitch
Real World Haskell :star::star::star: by Bryan O'Sullivan
Martin Odersky's Scala course :star::star: by Martin Odersky

0x0A ~ Computer Architecture

And luckily right at that moment my wife went on a 3 weeks vacation to take my one year old (roughly) to visit my in-laws who were in California, this period long, 1 week, 1 week, 1 week... and we had UnixKen Thompson, VCF East 2019


How Interesting Author
Digital Design and Computer Architecture :star::star::star::star: **
X86 vs ARM :star::star::star: Fossbytes
MIPS Processors :star::star: Stack Overflow

0x0B ~ Misc

...and Unix is an example of a proper name, and, is not likely to be in the dictionary everBrian W. Kernighan (1982)


How Interesting Author
UNIX AT&T Archives film from 1982 :two_hearts by Bell Laboratories
A Super Mario 64 decompilation :star::star::star::star::star: by a bunch of clever folks
The Go Programming Language :star::star::star::star::star: by Alan A. A. Donovan and Brian W. Kernighan
Vim 101 Quick Movement :star::star::star::star: Alex R. Young
Software Version Control Visualization : :star::star::star::star: by Andrew Caudwell
Math for Game Programmers: Dark Secrets of the RNG :star::star::star: by Shay Pierce
Clean Code :star::star::star: by Robert C. Martin
Why Java Suck :star: by Jonathan Gardner
XOR Linked List – A Memory Efficient Doubly Linked List :star: Wikipedia
XOR Linked List – C Implementation :star: StackOverFlow

0x0C ~ Mobile App Development


How Interesting Author
Framework: Flutter Hello World :two_hearts by Flutter Team (Google)
Images: About Webp :star::star: Suzanne Scacca

0x0D ~ Science-Fiction Masterpieces

To succeed, planning alone is insufficient. One must improvise as wellIsaac Asimov, Foundation


Title How Interesting Author
Book The Foundation :twohearts: by Isaac Asimov
Book The Hitchhiker's Guide to the Galaxy :twohearts: by Douglas Adams
AudioBook The Hitchhiker's Guide to the Galaxy :twohearts: by Douglas Adams and read by Stephen Moore
Movie Ready Player One :twohearts: by Steven Spielberg
Movie Matrix :two_hearts: by the Wachowskis
Book Hyperion :star::star::star::star: by Dan Simmons
Movie War Games :star::star::star: directed by John Badham
Book Elon Musk Biography :star::star::star::star::star: by Ashlee Vance


Boxer's Perfect Rush SCV

0x00 ~ Optimization - Aiming for the lowest latency

When you want to aim for lowest latency - i.e maximum speed - there are many things that will improve your program to create a better binary: Optimization flag, parallelization, vectorization and carefully crafting your algorithm.

Optimization flags

Especially for Computer Graphics projects, you will want to turn on these optimization flags, listed on gcc website.

Without any optimization option, the compiler’s goal is to reduce the cost of compilation and to make debugging produce the expected results. Statements are independent: if you stop the program with a breakpoint between statements, you can then assign a new value to any variable or change the program counter to any other statement in the function and get exactly the results you expect from the source code. Turning on optimization flags makes the compiler attempt to improve the performance and/or code size at the expense of compilation time and possibly the ability to debug the program.

To use it simply compile the program with:

gcc -O2 a.c
NB: It is the letter 'o' and not a zero. You may also use O3.

Multithreading and Parallelization

The historical (and current) approach is to add more power via multithreading, multiprocessing, Grid Computing or even Cloud Computing. Two libraries exist for this use: OpenMP and pthread, you will have to compile respectively with:

gcc -fopenmp -O3 a.c
gcc -pthread -O3 a.c


Modern graphics processing units (GPUs) are often wide SIMD implementations, capable of branches, loads, and stores on 128 or 256 bits at a time. Intel's latest AVX-512 SIMD instructions now process 512 bits of data at once.

As a double is 64 bits - i.e 8 bytes or octets - instead of iterating overs value 1 by 1, you will be able to compute up to 8 double at the time - i.e 512 / 64 - if your computer support it (but most likely, as of 2020, your computer will only handle 256 bits register).

Vectorization the most efficient way to quickly gain performance gains without the overhead of threads' initialization.

Demonstration: Getting Min and Max value from a float array ```c /* Vectorization example by agavrel */

include // printf

include // rand()

include // time

include // 128 bits register _m128

float m128maxfloat(_m128 src) { _m128 n[4];

// a) n[0] = src >> 64                                  So lets say src is composed of floats a b c d, it becomes 0 0 a b
n[0] = _mm_shuffle_ps(src, src, _MM_SHUFFLE(0,0,3,2));
// b) n[1] = {max(a,0), max(b,0) max(a,c) max(b,d)}     NB: actually we don't care about the two highest float at this point, I will call them 'x': {x, x max(a,c) max(b,d)}
n[1] = _mm_max_ps(src, n[0]);                             
// c) n[2] = n[1] >> 32                                 So n2 become {0 x x max(a,c)}
n[2] = _mm_shuffle_ps(n[1], n[1], _MM_SHUFFLE(0,0,0,1));
// d) n[3] = {x x x max(max(a,c), max(b,d))}
n[3] = _mm_max_ps(n[1], n[2]);                            

return _mm_cvtss_f32(n[3]); // d) Hence max(a,b,c,d), stored in the lowest 32 bits of n[3], is loaded into a float that we return. We don't care about the other bits


float m128minfloat(_m128 src) { _m128 n[4];

n[0] = _mm_shuffle_ps(src, src, _MM_SHUFFLE(0,0,3,2));
n[1] = _mm_min_ps(src, n[0]);
n[2] = _mm_shuffle_ps(n[1], n[1], _MM_SHUFFLE(0,0,0,1));
n[3] = _mm_min_ps(n[1], n[2]);

return _mm_cvtss_f32(n[3]);


define SIZE 1000000000L // 1 billion. Yes.

void getminmax(long i, float array[i]) { _m128 max; _m128 min;

max = mmloadups(array); // will load first 4 float into max min = _mmloadups(array); // will load first 4 float into min while ((i -= 4L)) { _m128 tmp = mmloadups(array + i); max = _mmmaxps(max, tmp); min = _mmmin_ps(min, tmp); }

printf("Max value: %f\t Min value: %f\n", m128maxfloat(max), m128minfloat(min)); }

void getminmaxlikebocalian(long size, float array[size]) { float max; float min; int i;

max = array[0]; min = array[0]; i = 1L; while (i < size) { float tmp = array[i++]; max = tmp < max ? max : tmp; min = tmp > min ? min : tmp; }

printf("Max value: %f\t Min value: %f\n", max, min); }

int main() { long i; float *data; clock_t time;

srand(time(NULL)); // seed data = (float )malloc(SIZE * sizeof(float)); i = -1L; while (++i < SIZE) { data[i] = (float)rand() / (float)(RAND_MAX) * 1000.0f; / printf("%.02f\t\t", data[i]); // I commented these lines because it slows considerably the program. if (!(i & 15)) printf("\n");*/ }

time = clock(); getminmax(SIZE, data); time = clock() - time; double elapsedtime = ((double)time) / CLOCKSPERSEC; printf("Executed in %f seconds\n", elapsedtime);

time = clock(); getminmaxlikebocalian(SIZE, data); time = clock() - time; elapsedtime = ((double)time) / CLOCKSPERSEC; printf("Executed in %f seconds\n", elapsedtime);

return 0; } ```

And compile with:

gcc vectorization.c -O3  && ./a.out 

You will notice that the vectorized approach will be about 3 times faster (NB: For this specific example). If I was using mm256 or mm512 registers, the vectorized program would be even faster by a factor of 2 and 4 respectively.

Now that you realize the performance boost, how about using what you just learn for your RayTracing project?

Combining Optimization Flags, Parallelization and Vectorization

a) *You can take a look at this very interesting project** which aim to show how fast wc can get using the various tools C has to offer to optimize speed. After downloading the file, you will also need to download the header: simd.h, which make use of Intel intrinsic.*

b) Compile it with the flags:

gcc fastlwc-mt.c -fopenmp -O3

c) Create a random file:

dd if=/dev/urandom of=sample.txt bs=64M count=16 iflag=fullblock

d) Compare wc with the new binary with:

time ./a.out sample.txt \
&& time wc sample.txt

The Right Algorithm

The right algorithm is usually the corner stone of an efficient program.

How about solving this algorithm problem:

int32_t dancer_position(uint32_t time_elapsed) { ;}

Exploring Compiler's Assembly Output

Let's take and example with the brilliant UTF-8 implementation, especially at how continuation bytes are designed:

continuation bytes start with 10 while single bytes start with 0 and longer lead bytes start with 11

Let's say that you have to write a function that determines if the byte is a continuation one, you can think of many ways that would end with the same result. But they will have a different output in their assembly.

You can retain the two first bits wwith

& 0b11000000
and then make sure that the first one is set and the second one is not with
== 0b10000000
: ```c


bool isutf8continuation_byte(char c) { return ((c & 0b11000000) == 0b10000000);
} ```

Which corresponds to the following compiler output with

gcc x86-64 9.3 with -O3 optimization flag
and     edi, 192
cmp     edi, 128
sete    al

Another way would be to shift the bits to the right:

bool is_utf8_continuation_byte(char c) {
    return (!((((unsigned char)c >> 6) ^ 0b10)));
Here I cast c into unsigned in order to be able to shift the MSB to the right with
(unsigned char)c

Then I shift it 6 times to the right with
>> 6
because we do not care about the content of the 6 lowest bits.
Finally I xor the result by 0b10 with
^ 0b10
, which corresponds to specification of a continuation byte as quoted before. As a number xored by itself gives 0, I use the exclamation mark ! to reverse the result from 0 to 1. (Else we would have to rename the function

It is not producing the following output that you could imagine:

sar     edi, 6
xor     edi, 2
not     edi,

But the optimized version:

movzx   edi, dil
sar     edi, 6
cmp     edi, 2
sete    al
It's even less efficient.

Finally since the valid range 0b10111111 to 0b10000000 (corresponding to -128 to -65, both included), you can add 0b01000000 and check if the byte is negative:

bool is_utf8_continuation_byte(char c) {
    return (c + 0b01000000 < 0);

In other word you compare to -64 and check if it is lower:

cmp     dil, -64
setl    al

To see the assembly output you can use the following command which will generate an assembly file with intel syntax (more readable than AT&T):

gcc -O3 -S -masm=intel a.c && cat a.s

or use the excellent compiler explorer from godbolt

I hope that you liked this demonstration that shows that functions with same behaviors can produce different assembly output, hence being more or less efficient. If you want to build your program to be the most efficient you should explore the assembly code of functions in critical loops

0x01 ~ Computer Graphics - Using SDL2 to create Fractal

Using SDL2 to create Computer Graphics

You can follow tutorials to create a simple program with SDL on Lazyfoo's website or on SDL2 official website.

You will also have to install SDL2:

brew install sdl2

With SDL2 you have to first

- see function below. Then you will keep the user entertained with a loop
while (42)
that can only be escaped by clicking on the the close button or pressing escape. While the loop is active, user's actions will be recorded thanks to
. You then draw pixel by using
and you refresh image with

Example with a Barnsley Fern Fractal

Michael Barnsley was a British mathematician who coined a fractal algorithm to represent a fern.

Barnsley Fern

The algorithm is explained in detail on wikipedia

Find below the code for the whole program, compile it with :

gcc barnsley.c -lSDL2 -O3

You will need about 10 000 iterations of n to draw the shape. On each keypress you will increase the number of iterations by 400. ```c

pragma message "\033[1;31mRequire SDL2\033[0m, \033[1;92mbrew install sdl2\033[0m and compile with \033[1;5;36mgcc barnsley.c -lSDL2\033[0m && ./a.out " FILE "..."

// gcc main.c -lSDL2 -O3 -Wall -Werror -Wextra --pedantic&& ./a.out




define WINDOW_WIDTH 600

define WINDOW_HEIGHT 800

typedef struct scnb { double real; double imag; } tcnb;

typedef struct spixel { int x; int y; } tpixel;

void barnsley(SDLRenderer *renderer, tcnb *c) { float rng; t_pixel i; static const float probability[3] = {0.01f, 0.08f, 0.15f}; long n = 400;

while (n--) {
    rng = ((float)rand() / (float)RAND_MAX);
    if (rng <= probability[0]) {
        c->real = 0;
        c->imag *= 0.16f;
    else if (rng <= probability[1]){
        c->real = -0.15f * c->real + 0.28f * c->imag;
        c->imag = 0.26f * c->real + 0.24f * c->imag + 0.44f;
    else if (rng <= probability[2]) {
        c->real = 0.2f * c->real + -0.26f * c->imag;
        c->imag = 0.23f * c->real + 0.22f * c->imag + 1.6f;
    else {
        c->real = 0.85f * c->real + 0.04f * c->imag;
        c->imag = -0.04f * c->real + 0.85f * c->imag + 1.6f;
    i.x = (c->real + 3) * 70;
    i.y = WINDOW_HEIGHT - c->imag * 70;
    SDL_RenderDrawPoint(renderer, i.x, i.y);


bool errorsdl(char *errormsg) { printf( "%s! SDLError: %s\n", errormsg, SDL_GetError() ); return false; }

bool initsdl(SDLWindow *window, SDL_Renderer *renderer) { if (SDLInit(SDLINITVIDEO) < 0) return (errorsdl("SDL could not initialize!")); SDLCreateWindowAndRenderer(WINDOWWIDTH, WINDOWHEIGHT, 0, window, renderer); if (*window == NULL) return (errorsdl("Window could not be created!")); SDLSetRenderDrawColor(*renderer, 0, 0, 0, 0); SDLRenderClear(renderer); SDL_SetRenderDrawColor(renderer, 0xbf, 0xff, 0, 0);

return true;


int main(void) { SDLEvent event; SDLWindow *window; SDLRenderer *renderer; tcnb c;

if (!(init_sdl(&window, &renderer)))
    return 1;

c = (t_cnb) {.real = 0, .imag = 0}; // PS: legal for Norminette while (42) { if (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) break ; else if (event.type == SDL_KEYDOWN) { if (event.key.keysym.sym == SDLK_ESCAPE) break ; barnsley(renderer, &c); SDL_RenderPresent(renderer); } } } SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return EXIT_SUCCESS;

} ```

0x02 ~ Hacking - Buffer Overflow


Let's take a look at the function strcpy, shall we? Type

man strcpy
in your terminal:

The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest. The strings may not overlap, and the destination string dest must be large enough to receive the copy. Beware of buffer overruns! *(See BUGS.)***

NB: Usage of brackets for what is considered as one of the most critical security flaw in the world

If the destination string of a strcpy() is not large enough, then anything might happen ― NB: Undefined Behavior. Overflowing fixed-length string buffers is a favorite cracker technique for taking complete control of the machine. Any time a program reads or copies data into a buffer, the program first needs to check that there's enough space. This may be unnecessary if you can show that overflow is impossible, but be careful: programs can get changed over time, in ways that may make the impossible possible.*


int main(void) { char s[11];

strcpy(s, "hello world");

return 0;

} </stdio.h></string.h>

While this look okay if you count each letter, if you happen to read again the definition of strcpy (just above) you will notice:

including the terminating null byte ('\0')

So you are trying to copy 12 characters in fact, into a 11 characters buffer. You will get the nice message:

In function ‘main’:
warning: ‘__builtin_memcpy’ writing 12 bytes into a region of size 11 overflows the destination [-Wstringop-overflow=]
strcpy(s, "hello world");

In fact all functions that you will find in

represent potential security risks and should be avoided as much as possible.

Buffer overflow to hijack a password

#include  // for strcmp, compare two strings and return 0 if they are equal

char *strcpy_until(char *dst, char *src, char until) { int i = -1;

while (src[++i] != until)
    dst[i] = src[i];

return (dst);


int main(int ac, char **av) { int n = 5; char password[] = "sarang hae"; // we don't know char buffer[4] = "kkk";

if (ac != 2)
    return 1;
printf("n equals %d\n", n);
printf("you would have never guessed, password was '%s'\n\n", password);
char *s = &amp;buffer[3];
char shellcode[] = "\x42\x61\x67\x61\x76\x72\x65\x6c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2a\x00\x00\x01";
strcpy_until(s, shellcode, '\x01');
printf("n equals '%d'\n", n);
printf("password now equals: '%s'\n", password);

if (!strcmp(password, av[1])) {
    printf("\nSuccessfully hacked user with password \e[1;5;92m%s\e[0m\n", password);        
return 0;

} </string.h></stdio.h>

Would you have guessed the password?

Some explanations: *

will copy until a specific character, hence allowing to bypass the NULL that terminates the string *
char shellcode[]
can be used to, instead of just replacing value at memory addresses, execute the value that have been replaced. See next below...

Shellcode Execution to get root access

When something is important enough, you do it even if the odds are not in your favorElon Musk

You will now have to compile with:

gcc -fno-stack-protector -z execstack a.c
  • -fno-stack-protector a.c
    is to disable the Stack-Guard mechanism
  • Compiler make prevent stack from being executable and
    -z execstack
    reverse that protection.

Last you will also temporarily disable randomize va space with:

sudo sysctl -w kernel.randomize_va_space=0
NB: You can use safer method
setarch `uname -m` -R /bin/bash
which is more safe

Once done with experiments do not forget to set back randomize back to normal:

sysctl -a --pattern "randomize" && \
sudo sysctl -w kernel.randomize_va_space=2


0x03 ~ Chess Bitboard

Often you will have programs where you want to represent data the following way:

int map[8][8];

While it looks like it is convenient, you can make it convenient using the right functions. But if you are using an integer to tell if the board is filled with pieces, you are wasting a lot of memory.


using namespace std;

void print_binary(uint64_t n) { uint64_t mask = 0; for (mask = mask ^ (mask >> 1); mask != 0; mask >>= 1) putchar('0' + !!(n & mask)); putchar('\n'); }

void fill_board(uint64_t board[12], uint64_t *used_cells) { const uint64_t initial_pos[6] = { 0b0000000011111111000000000000000000000000000000001111111100000000, // most right is a1, most left is h8 0b1000000100000000000000000000000000000000000000000000000010000001, 0b0100001000000000000000000000000000000000000000000000000001000010, 0b0010010000000000000000000000000000000000000000000000000000100100, 0b0001000000000000000000000000000000000000000000000000000000001000, 0b0000100000000000000000000000000000000000000000000000000000010000 }; const uint64_t color_mask[2] = { 0b0000000000000000000000000000000011111111111111111111111111111111, 0b1111111111111111111111111111111100000000000000000000000000000000 };

*used_cells = 0;
for (int i = 0; i &lt; 12; i++) {
    board[i] = (initial_pos[i &gt;&gt; 1]) &amp; (color_mask[i &amp; 1]);
    *used_cells |= board[i];


void display_board(uint64_t board[12]) { for (int i = 0; i < 12; i++) print_binary(board[i]); }

std::map fill_move() { std::map move;

for (char r = '1'; r &lt;= '8'; r++) {
    for (char c = 'a'; c &lt;= 'h'; c++) {
        char cell[3] = {c, r, '\0'};
        move[cell] = (1UL &lt;&lt; (8 * (c - 'a'))) &lt;&lt; (r - '1');
return move;



int main() {
uint64_t board[12]; uint64_t used_cells; std::map move = fill_move();

fill_board(board, &amp;used_cells);


if (board[__PAWN_W] &amp; move["b4"]) // check if exist
    board[__PAWN_W] ^=  ((move["b4"] | move["e4"]));


return 0;



0x00 ~ Wanted Pull Requests

If you know how to make software, then you can create big thingsXavier Niel

One function related to each 42 project to help students get started
In-depth examples with pointers
Books on system design
Exemple of a Makefile "qui fait le cafe"

0x01 ~ Question ? Broken Link ? Wanna contribute ?

I think it's very important to have a feedback loop, where you're constantly thinking about what you've done and how you could be doing it betterElon Musk

Raise an issue or even better: submit a pull request

First fork the repository and clone it locally (you will be forgiven for this kind of git clone)

Make the desired changed to the file

Then open the terminal containing your fork and enter:

git checkout -b agavrel
git commit -am "[ADD] Interesting link about C Hash"
git push --set-upstream origin agavrel

Go back to internet and you will see that you can submit a pull request.

I will personally review contributions

0x02 ~ Liked it ?

Show your appreciation by starring the repo, sharing on slack, RT and 'lache un com magueule' skyblog™

Kimg Jeong Un applauding

잘했어 동무 계속 배우자Good Job Comrade, let's keep studying

:musical_score: 0x2A ~ About the Author

Antonin GAVREL

Feel free to reach me on LinkedIn

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.