C Tutorial

   { Constant work in progress, mostly done but may still have some bugs.
   ~drummyfish }

   This is a relatively quick [1]C tutorial.

   You should probably how at least some basic awareness of essential
   programming concepts before reading this (what's a [2]programming
   language, [3]source code, [4]command line etc.). If you're as far as
   already somewhat knowing another language, this should be pretty easy to
   understand.

   This tutorial focuses on teaching pure C, i.e. mostly just command line
   text-only programs. There is a small bonus that shows some very basics of
   doing graphics programming at the end, but bear in mind it's inevitable to
   learn step by step, as much as you want to start programming graphical
   games, you first HAVE TO learn the language itself well. Don't rush it.
   Trust this advice, it is sincere.

   If you do two chapters a day (should take like half and hour), in a week
   you'll know some basic C.

   Potentially supplemental articles to this tutorial are:

     * [5]C
     * [6]algorithm
     * [7]programming tips
     * [8]programming style
     * [9]debugging
     * [10]exercises
     * [11]C pitfalls
     * [12]memory management
     * [13]optimization
     * [14]SAF
     * [15]SDL
     * ...

About C And Programming

   [16]C is

     * A [17]programming language, i.e. a language that lets you express
       [18]algorithms.
     * [19]Compiled language (as opposed to [20]interpreted), i.e. you have
       to compile the code you write (with [21]compiler) in order to obtain a
       [22]native executable program (a binary file that you can run
       directly).
     * Extremely fast and efficient.
     * Very widely supported and portable to almost anything.
     * [23]Low level, i.e. there is relatively little [24]abstraction and not
       many comfortable built-in functionality such as [25]garbage
       collection, you have to write many things yourself, you will deal with
       [26]pointers, [27]endianness etc.
     * [28]Imperative (based on sequences of commands), without [29]object
       oriented programming.
     * Considered hard, but in certain ways it's simple, it lacks [30]bloat
       and [31]bullshit of "[32]modern" languages which is an essential
       thing. It will take long to learn (don't worry, not nearly as long as
       learning a foreign language) but it's the most basic thing you should
       know if you want to create good software. You won't regret.
     * Not holding your hand, i.e. you may very easily "shoot yourself in
       your foot" and crash your program. This is the price for the
       language's power.
     * Very old, well established and tested by time.
     * Recommended by us for serious programs.

   If you come from a language like [33]Python or [34]JavaScript, you may be
   shocked that C doesn't come with its own [35]package manager, [36]debugger
   or [37]build system, it doesn't have [38]modules, [39]generics,
   [40]garabage collection, [41]OOP, [42]hashmaps, dynamic [43]lists,
   [44]type inference and similar "[45]modern" features. When you truly get
   into C, you'll find it's a good thing.

   Programming in C works like this:

    1. You write a C source code into a file.
    2. You compile the file with a C [46]compiler such as [47]gcc (which is
       just a program that turns source code into a runnable program). This
       gives you the executable program.
    3. You run the program, test it, see how it works and potentially get
       back to modifying the source code (step 1).

   So, for writing the source code you'll need a [48]text editor; any
   [49]plain text editor will do but you should use some that can highlight C
   [50]syntax -- this helps very much when programming and is practically a
   necessity. Ideal editor is [51]vim but it's a bit difficult to learn so
   you can use something as simple as [52]Gedit or [53]Geany. We do NOT
   recommend using huge programming [54]IDEs such as "VS Code" and whatnot.
   You definitely can NOT use an advanced document editor that works with
   [55]rich text such as [56]LibreOffice or that [57]shit from Micro$oft,
   this won't work because it's not plain text.

   Next you'll need a C [58]compiler, the program that will turn your source
   code into a runnable program. We'll use the most commonly used one called
   [59]gcc (you can try different ones such as [60]clang or [61]tcc if you
   want). If you're on a [62]Unix-like system such as [63]GNU/[64]Linux
   (which you probably should), gcc is probably already installed. Open up a
   terminal and write gcc to see if it's installed -- if not, then install it
   (e.g. with sudo apt install build-essential if you're on a Debian-based
   system).

   If you're extremely lazy, there are online web C compilers that work in a
   web browser (find them with a search engine). You can use these for quick
   experiments but note there are some limitations (e.g. not being able to
   work with files), and you should definitely know how to compile programs
   yourself.

   Last thing: there are multiple standards of C. Here we will be covering
   [65]C99, but this likely doesn't have to bother you at this point.

First Program

   Let's quickly try to compile a tiny program to test everything and see how
   everything works in practice.

   Open your text editor and paste this code:

 /* simple C program! */

 #include <stdio.h> // include IO library

 int main(void)
 {
   puts("It works.");
  
   return 0;
 }

   Save this file and name it program.c. Then open a terminal emulator (or an
   equivalent command line interface), locate yourself into the directory
   where you saved the file (e.g. cd somedirectory) and compile the program
   with the following command:

 gcc -o program program.c

   The program should compile and the executable program should appear in the
   directory. You can run it with

 ./program

   And you should see

 It works.

   written in the command line.

   Now let's see what the source code means:

     * /* simple C program! */ is so called block comment, it does nothing,
       it's here only for the humans that will read the source code. Such
       comments can be almost anywhere in the code. The comment starts at /*
       and ends with */.
     * // include IO library is another comment, but this is a line comment,
       it starts with // and ends with the end of line.
     * #include <stdio.h> tells the compiler we want to include a library
       named stdio (the weird [66]syntax will be explained in the future).
       This is a standard library with input output functions, we need it to
       be able to use the function puts later on. We can include more
       libraries if we want to. These includes are almost always at the very
       top of the source code.
     * int main(void) is the start of the main program. What exactly this
       means will be explained later, for now just remember there has to be
       this function named main in basically every program -- inside it there
       are commands that will be executed when the program is run. Note that
       the curly brackets that follow ({ and }) denote the block of code that
       belongs to this function, so we need to write our commands between
       these brackets.
     * puts("It works."); is a "command" for printing text strings to the
       command line (it's a command from the stdio library included above).
       Why exactly this is written like this will be explained later, but for
       now notice the following. The command starts with its name (puts, for
       put string), then there are left and right brackets (( and )) between
       which there are arguments to the command, in our case there is one,
       the text string "It works.". Text strings have to be put between
       quotes ("), otherwise the compiler would think the words are other
       commands (the quotes are not part of the string itself, they won't be
       printed out). The command is terminated by ; -- all "normal" commands
       in C have to end with a semicolon.
     * return 0; is another "command", it basically tells the operating
       system that everything was terminated successfully (0 is a code for
       success). This command is an exception in that it doesn't have to have
       brackets (( and )). This doesn't have to bother us too much now, let's
       just remember this will always be the last command in our program.

   Also notice how the source code is formatted, e.g. the indentation of code
   within the { and } brackets. White characters (spaces, new lines, tabs)
   are ignored by the compiler so we can theoretically write our program on a
   single line, but that would be unreadable. We use indentation, spaces and
   empty lines to format the code to be well readable.

   To sum up let's see a general structure of a typical C program. You can
   just copy paste this for any new program and then just start writing
   commands in the main function.

 #include <stdio.h> // include the I/O library
 // more libraries can be included here

 int main(void)
 {
   // write commands here
  
   return 0; // always the last command
 }

Variables, Arithmetic, Data Types

   Programming is a lot like mathematics, we compute equations and transform
   numerical values into other values. You probably know in mathematics we
   use variables such as x or y to denote numerical values that can change
   (hence variables). In programming we also use variables -- here
   [67]variable is a place in memory which has a name (and in this place
   there will be stored a value that can change over time).

   We can create variables named x, y, myVariable or score and then store
   specific values (for now let's only consider numbers) into them. We can
   read from and write to these variables at any time. These variables
   physically reside in [68]RAM, but we don't really care where exactly (at
   which address) they are located -- this is e.g. similar to houses, in
   common talk we normally say things like John's house or the pet store
   instead of house with address 3225.

   Variable names can't start with a digit (and they can't be any of the
   [69]keywords reserved by C). By convention they also shouldn't be all
   uppercase or start with uppercase (these are normally used for other
   things). Normally we name variables like this: myVariable or my_variable
   (pick one style, don't mix them).

   In C as in other languages each variable has a certain [70]data type; that
   is each variable has associated an information of what kind of data is
   stored in it. This can be e.g. a whole number, fraction, a text character,
   text string etc. Data types are a more complex topic that will be
   discussed later, for now we'll start with the most basic one, the integer
   type, in C called int. An int variable can store whole numbers in the
   range of at least -32768 to 32767 (but usually much more).

   Let's see an example.

 #include <stdio.h>

 int main(void)
 {
   int myVariable;
  
   myVariable = 5;
  
   printf("%d\n",myVariable);
  
   myVariable = 8;
  
   printf("%d\n",myVariable);
 }

     * int myVariable; is so called variable declaration, it tells the
       compiler we are creating a new variable with the name myVariable and
       data type int. Variables can be created almost anywhere in the code
       (even outside the main function) but that's a topic for later.
     * myVariable = 5; is so called variable assignment, it stores a value 5
       into variable named myVariable. IMPORTANT NOTE: the = does NOT signify
       mathematical equality but an assignment (equality in C is written as
       ==); when compiler encounters =, it simply takes the value on the
       right of it and writes it to the variable on the left side of it.
       Sometimes people confuse assignment with an equation that the compiler
       solves -- this is NOT the case, assignment is much more simple, it
       simply writes a value into variable. So x = x + 1; is a valid command
       even though mathematically it would be an equation without a solution.
     * printf("%d\n",myVariable); prints out the value currently stored in
       myVariable. Don't get scared by this complicated command, it will be
       explained later (once we learn about [71]pointers). For now only know
       this prints the variable content.
     * myVariable = 8; assigns a new value to myVariable, overwriting the
       old.
     * printf("%d\n",myVariable); again prints the value in myVariable.

   After compiling and running of the program you should see:

 5
 8

   Last thing to learn is arithmetic operators. They're just normal math
   operators such as +, - and /. You can use these along with brackets (( and
   )) to create [72]expressions. Expressions can contain variables and can
   themselves be used in many places where variables can be used (but not
   everywhere, e.g. on the left side of variable assignment, that would make
   no sense). E.g.:

 #include <stdio.h>

 int main(void)
 {
   int heightCm = 175;
   int weightKg = 75;
   int bmi = (weightKg * 10000) / (heightCm * heightCm);

   printf("%d\n",bmi);
 }

   calculates and prints your BMI (body mass index).

   Let's quickly mention how you can read and write values in C so that you
   can begin to experiment with your own small programs. You don't have to
   understand the following [73]syntax as of yet, it will be explained later,
   now simply copy-paste the commands:

     * puts("hello");: Prints a text string with newline.
     * printf("hello");: Same as above but without newline.
     * printf("%d\n",x);: Prints the value of variable x with newline.
     * printf("%d ");: Same as above but without a newline.
     * scanf("%d",&x);: Read a number from input to the variable x. Note
       there has to be & in front of x.

Branches And Loops (If, While, For)

   When creating [74]algorithms, it's not enough to just write linear
   sequences of commands. Two things (called [75]control structures) are very
   important to have in addition:

     * [76]branches: Conditionally executing or skipping certain commands
       (e.g. if a user enters password we want to either log him in if the
       password was correct or write error if the password was incorrect).
       This is informally known as "if-then-else".
     * [77]loops (also called iteration): Repeating certain commands given
       number of times or as long as some condition holds (e.g. when
       searching a text we repeatedly compare words one by one to the
       searched word until a match is found or end of text is reached).

   Let's start with branches. In C the command for a branch is if. E.g.:

 if (x > 10)
   puts("X is greater than 10.");

   The [78]syntax is given, we start with if, then brackets (( and )) follow
   inside which there is a condition, then a command or a block of multiple
   commands (inside { and }) follow. If the condition in brackets holds, the
   command (or block of commands) gets executed, otherwise it is skipped.

   Optionally there may be an else branch which is gets executed only if the
   condition does NOT hold. It is denoted with the else keyword which is
   again followed by a command or a block of multiple commands. Branching may
   also be nested, i.e. branches may be inside other branches. For example:

 if (x > 10)
   puts("X is greater than 10.");
 else
 {
   puts("X is not greater than 10.");

   if (x < 5)
     puts("And it is also smaller than 5.");
 }

   So if x is equal e.g. 3, the output will be:

 X is not greater than 10.
 And it is also smaller than 5.

   About conditions in C: a condition is just an expression
   (variables/functions along with arithmetic operators). The expression is
   evaluated (computed) and the number that is obtained is interpreted as
   true or false like this: in C 0 (zero) means false, 1 (and everything
   else) means true. Even comparison operators like < and > are technically
   arithmetic, they compare numbers and yield either 1 or 0. Some operators
   commonly used in conditions are:

     * == (equals): yields 1 if the operands are equal, otherwise 0.
     * != (not equal): yields 1 if the operands are NOT equal, otherwise 0.
     * < (less than): yields 1 if the first operand is smaller than the
       second, otherwise 0.
     * <=: yields 1 if the first operand is smaller or equal to the second,
       otherwise 0.
     * && (logical [79]AND): yields 1 if both operands are non-0, otherwise
       0.
     * || (logical [80]OR): yields 1 if at least one operand is non-0,
       otherwise 0.
     * ! (logical [81]NOT): yields 1 if the operand is 0, otherwise 0.

   E.g. an if statement starting as if (x == 5 || x == 10) will be true if x
   is either 5 or 10.

   Next we have loops. There are multiple kinds of loops even though in
   theory it is enough to only have one kind of loop (there are multiple
   types out of convenience). The loops in C are:

     * while: Loop with condition at the beginning.
     * do while: Loop with condition at the end, not used so often so we'll
       ignore this one.
     * for: Loop executed a fixed number of times. This is a very common
       case, that's why there is a special loop for it.

   The while loop is used when we want to repeat something without knowing in
   advance how many times we'll repeat it (e.g. searching a word in text). It
   starts with the while keyword, is followed by brackets with a condition
   inside (same as with branches) and finally a command or a block of
   commands to be looped. For instance:

 while (x > y) // as long as x is greater than y
 {
   printf("%d %d\n",x,y); // prints x and y 

   x = x - 1; // decrease x by 1
   y = y * 2; // double y
 }

 puts("The loop ended.");

   If x and y were to be equal 100 and 20 (respectively) before the loop is
   encountered, the output would be:

 100 20
 99 40
 98 60
 97 80
 The loop ended.

   The for loop is executed a fixed number of time, i.e. we use it when we
   know in advance how many time we want to repeat our commands. The
   [82]syntax is a bit more complicated: it starts with the keywords for,
   then brackets (( and )) follow and then the command or a block of commands
   to be looped. The inside of the brackets consists of an initialization,
   condition and action separated by semicolon (;) -- don't worry, it is
   enough to just remember the structure. A for loop may look like this:

 puts("Counting until 5...");

 for (int i = 0; i < 5; ++i)
   printf("%d\n",i); // prints i

   int i = 0 creates a new temporary variable named i (name normally used by
   convention) which is used as a counter, i.e. this variable starts at 0 and
   increases with each iteration (cycle), and it can be used inside the loop
   body (the repeated commands). i < 5 says the loop continues to repeat as
   long as i is smaller than 5 and ++i says that i is to be increased by 1
   after each iteration (++i is basically just a shorthand for i = i + 1).
   The above code outputs:

 Counting until 5...
 0
 1
 2
 3
 4

   IMPORTANT NOTE: in programming we count from 0, not from 1 (this is
   convenient e.g. in regards to [83]pointers). So if we count to 5, we get
   0, 1, 2, 3, 4. This is why i starts with value 0 and the end condition is
   i < 5 (not i <= 5).

   Generally if we want to repeat the for loop N times, the format is for
   (int i = 0; i < N; ++i).

   Any loop can be exited at any time with a special command called break.
   This is often used with so called infinite loop, a while loop that has 1
   as a condition; recall that 1 means true, i.e. the loop condition always
   holds and the loop never ends. break allows us to place conditions in the
   middle of the loop and into multiple places. E.g.:

 while (1) // infinite loop
 {
   x = x - 1;
  
   if (x == 0)
     break; // this exits the loop!
    
   y = y / x;
 }

   The code above places a condition in the middle of an infinite loop to
   prevent division by zero in y = y / x.

   Again, loops can be nested (we may have loops inside loops) and also loops
   can contain branches and vice versa.

Simple Game: Guess A Number

   With what we've learned so far we can already make a simple [84]game:
   guess a number. The computer thinks a random number in range 0 to 9 and
   the user has to guess it. The source code is following.

 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>

 int main(void)
 {
   srand(clock()); // random seed
  
   while (1) // infinite loop
   {
     int randomNumber = rand() % 10;
      
     puts("I think a number. What is it?");
    
     int guess;
    
     scanf("%d",&guess); // read the guess
    
     getchar();

     if (guess == randomNumber)
       puts("You guessed it!");
     else
       printf("Wrong. The number was %d.\n",randomNumber);
      
     puts("Play on? [y/n]");
    
     char answer;

     scanf("%c",&answer); // read the answer
    
     if (answer == 'n')
       break;
   }

   puts("Bye.");
  
   return 0; // return success, always here
 }

     * #include <stdlib.h>, #include <time.h>: we're including additional
       libraries because we need some specific functions from them (rand,
       srand, clock).
     * srand(clock());: don't mind this line too much, its purpose is to
       [85]seed a pseudorandom number generator. Without doing this the game
       would always generate the same sequence of random numbers when run
       again.
     * while (1) is an infinite game loop -- it runs over and over, in each
       cycle we perform one game round. The loop can be exited with the break
       statement later on (if the user answers he doesn't want to continue
       playing).
     * int randomNumber = rand() % 10;: this line declares a variable named
       randomNumber and immediately assigns a value to it. The value is a
       random number from 0 to 9. This is achieved with a function rand (from
       the above included stdlib library) which returns a random number, and
       with the modulo (remainder after division) arithmetic operator (%)
       which ensures the number is in the correct range (less than 10).
     * int guess; creates another variable in which we'll store the user's
       guessed number.
     * scanf("%d",&guess); reads a number from the input to the variable
       named guess. Again, don't be bothered by the complicated structure of
       this command, for now just accept that this is how it's done.
     * getchar();: don't mind this line, it just discards a newline character
       read from the input.
     * if (guess == randomNumber) ...: this is a branch which checks if the
       user guess is equal to the generated random number. If so, a success
       message is printed out. If not, a fail message is printed out along
       with the secret number. Note we use the puts function for the first
       message as it only prints a text sting, while for the latter message
       we have to use printf, a more complex function, because that requires
       inserting a number into the printed string. More on these functions
       later.
     * char answer; declares a variable to store user's answer to a question
       of whether to play on. It is of char data type which can store a
       single text character.
     * scanf("%c",&answer); reads a single character from input to the answer
       variable.
     * if (answer == 'n') break; is a branch that exits the infinite loop
       with break statement if the answer entered was n (no).

Functions (Subprograms)

   Functions are extremely important, no program besides the most primitive
   ones can be made without them (well, in theory any program can be created
   without functions, but in practice such programs would be extremely
   complicated and unreadable).

   [86]Function is a subprogram (in other languages functions are also called
   procedures or subroutines), i.e. it is code that solves some smaller
   subproblem that you can repeatedly invoke, for instance you may have a
   function for computing a [87]square root, for encrypting data or for
   playing a sound from speakers. We have already met functions such as puts,
   printf or rand.

   Functions are similar to but NOT the same as mathematical functions.
   Mathematical function (simply put) takes a number as input and outputs
   another number computed from the input number, and this output number
   depends only on the input number and nothing else. C functions can do this
   too but they can also do additional things such as modify variables in
   other parts of the program or make the computer do something (such as play
   a sound or display something on the screen) -- these are called [88]side
   effects; things done besides computing an output number from an input
   number. For distinction mathematical functions are called pure functions
   and functions with side effects are called non-pure.

   Why are function so important? Firstly they help us divide a big problem
   into small subproblems and make the code better organized and readable,
   but mainly they help us respect the [89]DRY (Don't Repeat Yourself)
   principle -- this is extremely important in programming. Imagine you need
   to solve a [90]quadratic equation in several parts of your program; you do
   NOT want to solve it in each place separately, you want to make a function
   that solves a quadratic equation and then only invoke (call) that function
   anywhere you need to solve your quadratic equation. This firstly saves
   space (source code will be shorter and compiled program will be smaller),
   but it also makes your program manageable and eliminates bugs -- imagine
   you find a better (e.g. faster) way to solving quadratic equations;
   without functions you'd have to go through the whole code and change the
   algorithm in each place separately which is impractical and increases the
   chance of making errors. With functions you only change the code in one
   place (in the function) and in any place where your code invokes (calls)
   this function the new better and updated version of the function will be
   used.

   Besides writing programs that can be directly executed programmers write
   [91]libraries -- collections of functions that can be used in other
   projects. We have already seen libraries such as stdio, standard
   input/output library, a standard (official, bundled with every C compiler)
   library for input/output (reading and printing values); stdio contains
   functions such as puts which is used to printing out text strings.
   Examples of other libraries are the standard math library containing
   function for e.g. computing [92]sine, or [93]SDL, a 3rd party multimedia
   library for such things as drawing to screen, playing sounds and handling
   keyboard and mouse input.

   Let's see a simple example of a function that writes out a temperature in
   degrees of Celsius as well as in Kelvin:

 #include <stdio.h>

 void writeTemperature(int celsius)
 {
   int kelvin = celsius + 273;
   printf("%d C (%d K)\n",celsius,kelvin);
 }

 int main(void)
 {
   writeTemperature(-50);
   writeTemperature(0);
   writeTemperature(100);

   return 0;
 }

   The output is

 -50 C (223 K)
 0 C (273 K)
 100 C (373 K)

   Now imagine we decide we also want our temperatures in Fahrenheit. We can
   simply edit the code in writeTemperature function and the program will
   automatically be writing temperatures in the new way.

   Let's see how to create and invoke functions. Creating a function in code
   is done between inclusion of libraries and the main function, and we
   formally call this defining a function. The function definition format is
   following:

 RETURN_TYPE FUNCTION_NAME(FUNCTION_PARAMETERS)
 {
   FUNCTION_BODY
 }

     * RETURN_TYPE is the [94]data type the function returns. A function may
       or may not return a certain value, just as the pure mathematical
       function do. This may for example be int, if the function returns an
       integer number. If the function doesn't return anything, this type is
       void.
     * FUNCTION_NAME is the name of the function, it follows the same rules
       as the names for variables.
     * FUNCTION_PARAMETERS specifies the input values of the function. The
       function can take any number of parameters (e.g. a function playBeep
       may take 0 arguments, sine function takes 1, logarithm may take two
       etc.). This list is comma-separated and each item consists of the
       parameter data type and name. If there are 0 parameters, there should
       be the word void inside the brackets, but compilers tolerate just
       having empty brackets.
     * FUNCTION_BODY are the commands executed by the function, just as we
       know them from the main function.

   Let's see another function:

 #include <stdio.h>

 int power(int x, int n)
 {
   int result = 1;
  
   for (int i = 0; i < n; ++i) // repeat n times
     result = result * x;
    
   return result;
 }

 int main(void)
 {
   for (int i = 0; i < 5; ++i)
   {
     int powerOfTwo = power(2,i);
     printf("%d\n",powerOfTwo);
   }

   return 0;
 }

   The output is:

 2
 4
 8
 16

   The function power takes two parameters: x and n, and returns x raised to
   the ns power. Note that unlike the first function we saw here the return
   type is int because this function does return a value. Notice the command
   return -- it is a special command that causes the function to terminate
   and return a specific value. In functions that return a value (their
   return type is not void) there has to be a return command. In function
   that return nothing there may or may not be one, and if there is, it has
   no value after it (return;);

   Let's focus on how we invoke the function -- in programming we say we call
   the function. The function call in our code is power(2,i). If a function
   returns a value (return type is not void), its function call can be used
   in any expression, i.e. almost anywhere where we can use a variable or a
   numerical value -- just imagine the function computes a return value and
   this value is substituted to the place where we call the function. For
   example we can imagine the expression power(3,1) + power(3,0) as simply 3
   + 1.

   If a function returns nothing (return type is void), it can't be used in
   expressions, it is used "by itself"; e.g. playBeep();. (Function that do
   return a value can also be used like this -- their return value is in this
   case simply ignored.)

   We call a function by writing its name (power), then adding brackets ((
   and )) and inside them we put arguments -- specific values that will
   substitute the corresponding parameters inside the function (here x will
   take the value 2 and n will take the current value of i). If the function
   takes no parameters (the function parameter list is void), we simply put
   nothing inside the brackets (e.g. playBeep(););

   Here comes the nice thing: we can nest function calls. For example we can
   write x = power(3,power(2,1)); which will result in assigning the variable
   x the value of 9. Functions can also call other functions (even
   themselves, see [95]recursion), but only those that have been defined
   before them in the source code (this can be fixed with so called
   [96]forward declarations).

   Notice that the main function we always have in our programs is also a
   function definition. The definition of this function is required for
   runnable programs, its name has to be main and it has to return int (an
   error code where 0 means no error). It can also take parameters but more
   on that later.

   These is the most basic knowledge to have about C functions. Let's see one
   more example with some pecularities that aren't so important now, but will
   be later.

 #include <stdio.h>

 void writeFactors(int x) // writes divisors of x
 {
   printf("factors of %d:\n",x);
  
   while (x > 1) // keep dividing x by its factors
   {
     for (int i = 2; i <= x; ++i) // search for a factor
       if (x % i == 0) // i divides x without remainder?
       {
         printf("  %d\n",i); // i is a factor, write it
         x = x / i; // divide x by i
         break; // exit the for loop
       }
   }
 }

 int readNumber(void)
 {
   int number;
  
   puts("Please enter a number to factor (0 to quit).");
   scanf("%d",&number);
  
   return number;
 }

 int main(void)
 {
   while (1) // infinite loop
   {
     int number = readNumber(); // <- function call

     if (number == 0) // 0 means quit
       break;
      
     writeFactors(number); // <- function call
   }
    
   return 0;
 }

   We have defined two functions: writeFactors and readNumber. writeFactors
   return no values but it has side effects (print text to the command line).
   readNumber takes no parameters but return a value; it prompts the user to
   enter a value and returns the read value.

   Notice that inside writeFactors we modify its parameter x inside the
   function body -- this is okay, it won't affect the argument that was
   passed to this function (the number variable inside the main function
   won't change after this function call). x can be seen as a [97]local
   variable of the function, i.e. a variable that's created inside this
   function and can only be used inside it -- when writeFactors is called
   inside main, a new local variable x is created inside writeFactors and the
   value of number is copied to it.

   Another local variable is number -- it is a local variable both in main
   and in readNumber. Even though the names are the same, these are two
   different variables, each one is local to its respective function
   (modifying number inside readNumber won't affect number inside main and
   vice versa).

   And a last thing: keep in mind that not every command you write in C
   program is a function call. E.g. control structures (if, while, ...) and
   special commands (return, break, ...) are not function calls.

More Details (Globals, Switch, Float, Forward Decls, Program Arguments, ...)

   We've skipped a lot of details and small tricks for simplicity. Let's go
   over some of them. Many of the following things are so called
   [98]syntactic sugar: convenient syntax shorthands for common operations.

   Multiple variables can be defined and assigned like this:

 int x = 1, y = 2, z;

   The meaning should be clear, but let's mention that z doesn't generally
   have a defined value here -- it will have a value but you don't know what
   it is (this may differ between different computers and platforms). See
   [99]undefined behavior.

   The following is a shorthand for using operators:

 x += 1;      // same as: x = x + 1;
 x -= 10;     // same as: x = x - 1;
 x *= x + 1;  // same as: x = x * (x + 1);
 x++;         // same as: x = x + 1;
 x--;         // same as: x = x - 1;
 // etc.

   The last two constructs are called [100]incrementing and
   [101]decrementing. This just means adding/subtracting 1.

   In C there is a pretty unique operator called the [102]ternary operator
   (ternary for having three [103]operands). It can be used in expressions
   just as any other operators such as + or -. Its format is:

 CONDITION ? VALUE1 : VALUE2

   It evaluates the CONDITION and if it's true (non-0), this whole expression
   will have the value of VALUE1, otherwise its value will be VALUE2. It
   allows for not using so many ifs. For example instead of

 if (x >= 10)
   x -= 10;
 else
   x = 10;

   we can write

 x = x >= 10 ? x - 10 : 10;

   [104]Global variables: we can create variables even outside function
   bodies. Recall than variables inside functions are called local; variables
   outside functions are called global -- they can basically be accessed from
   anywhere and can sometimes be useful. For example:

 #include <stdio.h>
 #include <stdlib.h> // for rand()

 int money = 0; // total money, global variable

 void printMoney(void)
 {
   printf("I currently have $%d.\n",money);
 }

 void playLottery(void)
 {
   puts("I'm playing lottery.");
  
   money -= 10; // price of lottery ticket
    
   if (rand() % 5) // 1 in 5 chance
   {
     money += 100;
     puts("I've won!");
   }
   else
     puts("I've lost!");

   printMoney();
 }

 void work(void)
 {
   puts("I'm going to work :(");
  
   money += 200; // salary

   printMoney();
 }

 int main()
 {
   work();
   playLottery();
   work();
   playLottery();
  
   return 0;
 }

   In C programs you may encounter a switch statement -- it is a control
   structure similar to a branch if which can have more than two branches. It
   looks like this:

   switch (x)
   {
     case 0: puts("X is zero. Don't divide by it."); break;
     case 69: puts("X is 69, haha."); break;
     case 42: puts("X is 42, the answer to everything."); break;
     default: printf("I don't know anything about X."); break;
   }

   Switch can only compare exact values, it can't e.g. check if a value is
   greater than something. Each branch starts with the keyword case, then the
   match value follows, then there is a colon (:) and the branch commands
   follow. IMPORTANT: there has to be the break; statement at the end of each
   case branch (we won't go into details). A special branch is the one
   starting with the word default that is executed if no case label was
   matched.

   Let's also mention some additional data types we can use in programs:

     * char: A single text character such as 'a', 'G' or '_'. We can assign
       characters as char c = 'a'; (single characters are enclosed in
       apostrophes similarly to how text strings are inside quotes). We can
       read a character as c = getchar(); and print it as putchar(c);.
       Special characters that can be used are \n (newline) or \t (tab).
       Characters are in fact small numbers (usually with 256 possible
       values) and can be used basically anywhere a number can be used (for
       example we can compare characters, e.g. if (c < 'b') ...). Later we'll
       see characters are basic building blocks of text strings.
     * unsigned int: Integer that can only take positive values or 0 (i.e. no
       negative values). It can store higher positive values than normal int
       (which is called a signed int).
     * long: Big integer, takes more memory but can store number in the range
       of at least a few billion.
     * float and double: [105]Floating point number (double is bigger and
       more precise than float) -- an approximation of [106]real numbers,
       i.e. numbers with a fractional part such as 2.5 or 0.0001. You can
       print these numbers as printf("%lf\n",x); and read them as
       scanf("%f",&x);.

   Here is a short example with the new data types:

 #include <stdio.h>

 int main(void)
 {
   char c;
   float f;
  
   puts("Enter character.");
   c = getchar(); // read character
  
   puts("Enter float.");
   scanf("%f",&f);
  
   printf("Your character is :%c.\n",c);
   printf("Your float is %lf\n",f);
 
   float fSquared = f * f;
   int wholePart = f; // this can be done
  
   printf("It's square is %lf.\n",fSquared);
   printf("It's whole part is %d.\n",wholePart);
  
   return 0;
 }

   Notice mainly how we can assign a float value into the variable of int
   type (int wholePart = f;). This can be done even the other way around and
   with many other types. C can do automatic type conversions ([107]casting),
   but of course, some information may be lost in this process (e.g. the
   fractional part).

   In the section about functions we said a function can only call a function
   that has been defined before it in the source code -- this is because the
   compiler read the file from start to finish and if you call a function
   that hasn't been defined yet, it simply doesn't know what to call. But
   sometimes we need to call a function that will be defined later, e.g. in
   cases where two functions call each other (function A calls function B in
   its code but function B also calls function A). For this there exist so
   called [108]forward declarations -- a forward declaration is informing
   that a function of certain name (and with certain parameters etc.) will be
   defined later in the code. Forward declaration look the same as a function
   definition, but it doesn't have a body (the part between { and }), instead
   it is terminated with a semicolon (;). Here is an example:

 #include <stdio.h>

 void printDecorated2(int x, int fancy); // forward declaration

 void printDecorated1(int x, int fancy)
 {
   putchar('~');
  
   if (fancy)
     printDecorated2(x,0); // would be error without f. decl.
   else
     printf("%d",x);
  
   putchar('~');
 }

 void printDecorated2(int x, int fancy)
 {
   putchar('>');
  
   if (fancy)
     printDecorated1(x,0);
   else
     printf("%d",x);
  
   putchar('<');
 }

 int main()
 {
   printDecorated1(10,1);
   putchar('\n'); // newline
   printDecorated2(20,1);
 }

   which prints

 ~>10<~
 >~20~<

   The functions printDecorated1 and printDecorated2 call each other, so this
   is the case when we have to use a forward declaration of printDecorated2.
   Also note the condition if (fancy) which is the same thing as if (fancy !=
   0) (imagine fancy being 1 and 0 and about what the condition evaluates to
   in each case).

   And one more important thing: our program as a whole can be passed
   parameters when it's executed, which inside the program we can access as
   so called command line arguments (also known as flags, switches etc.).
   This is important especially under [109]Unix operating systems where we
   run programs from command line and where programs often work in
   non-interactive ways and are composed into bigger programs (similarly to
   how we compose small C functions into one big program); command line
   arguments are similar to arguments we pass to functions, they can inform
   our program to behave in certain way, for example to open a certain config
   file at start, to run in fullscreen mode, to print help and so on. When we
   compile our programs with the gcc compiler, e.g. like gcc -o myprogram
   myprogram.c, all the text after gcc are in fact arguments telling gcc
   which program to compile, how to compile it, how to name the output and so
   on. To allow our program to receive these arguments we add two parameters
   to the main function, one called argc (argument count) of integer type,
   saying how many arguments we get, and another called argv (argument
   [110]vector) of pointer to a pointer to char type (please don't get
   scared), holding an array of strings (each argument will be of string
   type). Operating system will automatically fill these arguments in when
   our program is started. Here is a short example demonstrating this:

 #include <stdio.h>

 int main(int argc, char **argv)
 {
   puts("You passed these arguments:");

   for (int i = 0; i < argc; ++i)
     printf("- \"%s\"\n",argv[i]);

   return 0;
 }

   If you compile this program and run it e.g. like

 ./program hello these are "my arguments"

   The program will output:

 You passed these arguments:
 - "./program"
 - "hello"
 - "these"
 - "are"
 - "my arguments"

   Things to notice here are following: we passed 4 arguments but got 5 --
   the first argument is the path of our program itself, i.e. we will always
   get at least this argument. Then we also see that our arguments are
   separated by spaces, but if we put them into double quotes (like the last
   one), it will become just one argument, keeping the spaces (but not the
   quotes). For now this knowledge will suffice, you will most definitely
   encounter command line arguments in real programs -- now you know what
   they are.

Header Files, Libraries, Compilation/Building

   So far we've only been writing programs into a single source code file
   (such as program.c). More complicated programs consist of multiple files
   and libraries -- we'll take a look at this now.

   In C we normally deal with two types of source code files:

     * .c files: These files contain so called [111]implementation of
       algorithms, i.e. code that translates into actual program
       instructions. These files are what's handed to the compiler.
     * .h files, or [112]header files: These files typically contain
       declarations such as constants and function headers (but not their
       bodies, i.e. implementations).

   When we have multiple source code files, we typically have pairs of .c and
   .h files. E.g. if there is a library called mathfunctions, it will consist
   of files mathfunctions.c and mathfunctions.h. The .h file will contain the
   function headers (in the same manner as with forward declarations) and
   constants such as [113]pi. The .c file will then contain the
   implementations of all the functions declared in the .h file. But why do
   we do this?

   Firstly .h files may serve as a nice documentation of the library for
   programmers: you can simply open the .h file and see all the functions the
   library offers without having to skim over thousands of lines of code.
   Secondly this is for how multiple source code files are compiled into a
   single executable program.

   Suppose now we're compiling a single file named program.c as we've been
   doing until now. The compilation consists of several steps:

    1. The compiler reads the file program.c and makes sense of it.
    2. It then creates an intermediate file called program.o. This is called
       an [114]object file and is a binary compiled file which however cannot
       yet be run because it is not linked -- in this code all memory
       addresses are relative and it doesn't yet contain the code from
       external libraries (e.g. the code of printf).
    3. The compiler then runs a [115]linker which takes the file program.o
       and the object files of libraries (such as the stdio library) and it
       puts them all together into the final executable file called program.
       This is called linking; the code from the libraries is copied to
       complete the code of our program and the memory addresses are settled
       to some specific values.

   So realize that when the compiler is compiling our program (program.c),
   which contains function such as printf from a separate library, it doesn't
   have the code of these functions available -- this code is not in our
   file. Recall that if we want to call a function, it must have been defined
   before and so in order for us to be able to call printf, the compiler must
   know about it. This is why we include the stdio library at the top of our
   source code with #include <stdio.h> -- this basically copy-pastes the
   content of the header file of the stdio library to the top of our source
   code file. In this header there are forward declarations of functions such
   as printf, so the compiler now knows about them (it knows their name, what
   they return and what parameters they take) and we can call them.

   Let's see a small example. We'll have the following files (all in the same
   directory).

   library.h (the header file):

 // Returns the square of n.
 int square(int n);

   library.c (the implementation file):

 int square(int x)
 {
   // function implementation
   return x * x;
 }

   program.c (main program):

 #include <stdio.h>
 #include "library.h"

 int main(void)
 {
   int n = square(5);

   printf("%d\n",n);

   return 0;
 }

   NOTE: "library.h" here is between double quotes, unlike <stdio.h>. This
   just says we specify an absolute path to the file as it's not in the
   directory where installed libraries go.

   Now we will manually compile the library and the final program. First
   let's compile the library, in command line run:

 gcc -c -o library.o library.c

   The -c flag tells the compiler to only compile the file, i.e. only
   generate the object (.o) file without trying to link it. After this
   command a file library.o should appear. Next we compile the main program
   in the same way:

 gcc -c -o program.o program.c

   This will generate the file program.o. Note that during this process the
   compiler is working only with the program.c file, it doesn't know the code
   of the function square, but it knows this function exists, what it returns
   and what parameter it has thanks to us including the library header
   library.h with #include "library.h" (quotes are used instead of < and > to
   tell the compiler to look for the files in the current directory).

   Now we have the file program.o in which the compiled main function resides
   and file library.o in which the compiled function square resides. We need
   to link them together. This is done like this:

 gcc -o program program.o library.o

   For linking we don't need to use any special flag, the compiler knows that
   if we give it several .o files, it is supposed to link them. The file
   program should appear that we can already run and it should print

 25

   This is the principle of compiling multiple C files (and it also allows
   for combining C with other languages). This process is normally automated,
   but you should know how it works. The systems that automate this action
   are called [116]build systems, they are for example [117]Make and
   [118]Cmake. When using e.g. the Make system, the whole codebase can be
   built with a single command make in the command line.

   Some programmers simplify this whole process further so that they don't
   even need a build system, e.g. with so called [119]header-only libraries,
   but this is outside the scope of this tutorial.

   As a bonus, let's see a few useful compiler flags:

     * -O1, -O2, -O3: Optimize for speed (higher number means better
       optimization). Adding -O3 normally instantly speeds up your program.
       This is recommended.
     * -Os: Optimize for size, the same as above but the compiler will try to
       make as small executable as possible.
     * -Wall -Wextra -pedantic: The compiler will write more warnings and
       will be more strict. This can help spot many bugs.
     * -c: Compile only (generate object files, do not link).
     * -g: Include debug symbols, this will be important for [120]debugging.

Advanced Data Types And Variables (Structs, Arrays, Strings)

   Until now we've encountered simple data types such as int, char or float.
   These identify values which can take single atomic values (e.g. numbers or
   text characters). Such data types are called [121]primitive types.

   Above these there exist [122]compound data types (also complex or
   structured) which are composed of multiple primitive types. They are
   necessary for any advanced program.

   The first compound type is a structure, or [123]struct. It is a collection
   of several values of potentially different data types (primitive or
   compound). The following code shows how a struct can be created and used.

 #include <stdio.h>

 typedef struct
 {
   char initial; // initial of name
   int weightKg;
   int heightCm;
 } Human;

 int bmi(Human human)
 {
   return (human.weightKg * 10000) / (human.heightCm * human.heightCm);
 }

 int main(void)
 {
   Human carl;
  
   carl.initial = 'C';
   carl.weightKg = 100;
   carl.heightCm = 180;
  
   if (bmi(carl) > 25)
     puts("Carl is fat.");
    
   return 0;
 }

   The part of the code starting with typedef struct creates a new data type
   that we call Human (one convention for data type names is to start them
   with an uppercase character). This data type is a structure consisting of
   three members, one of type char and two of type int. Inside the main
   function we create a variable carl which is of Human data type. Then we
   set the specific values -- we see that each member of the struct can be
   accessed using the dot character (.), e.g. carl.weightKg; this can be used
   just as any other variable. Then we see the type Human being used in the
   parameter list of the function bmi, just as any other type would be used.

   What is this good for? Why don't we just create global variables such as
   carl_initial, carl_weightKg and carl_heightCm? In this simple case it
   might work just as well, but in a more complex code this would be
   burdening -- imagine we wanted to create 10 variables of type Human (john,
   becky, arnold, ...). We would have to painstakingly create 30 variables (3
   for each person), the function bmi would have to take two parameters
   (height and weight) instead of one (human) and if we wanted to e.g. add
   more information about every human (such as hairLength), we would have to
   manually create another 10 variables and add one parameter to the function
   bmi, while with a struct we only add one member to the struct definition
   and create more variables of type Human.

   Structs can be nested. So you may see things such as
   myHouse.groundFloor.livingRoom.ceilingHeight in C code.

   Another extremely important compound type is [124]array -- a sequence of
   items, all of which are of the same data type. Each array is specified
   with its length (number of items) and the data type of the items. We can
   have, for instance, an array of 10 ints, or an array of 235 Humans. The
   important thing is that we can index the array, i.e. we access the
   individual items of the array by their position, and this position can be
   specified with a variable. This allows for looping over array items and
   performing certain operations on each item. Demonstration code follows:

 #include <stdio.h>
 #include <math.h> // for sqrt()

 int main(void)
 {
   float vector[5];
  
   vector[0] = 1;
   vector[1] = 2.5;
   vector[2] = 0;
   vector[3] = 1.1;
   vector[4] = -405.054;
  
   puts("The vector is:");
  
   for (int i = 0; i < 5; ++i)
     printf("%lf ",vector[i]);
  
   putchar('\n'); // newline
  
   /* compute vector length with
      pythagoren theorem: */
  
   float sum = 0;
  
   for (int i = 0; i < 5; ++i)
     sum += vector[i] * vector[i];
  
   printf("Vector length is: %lf\n",sqrt(sum));
  
   return 0;
 }

   We've included a new library called math.h so that we can use a function
   for square root (sqrt). (If you have trouble compiling the code, add -lm
   flag to the compile command.)

   float vector[5]; is a declaration of an array of length 5 whose items are
   of type float. When compiler sees this, it creates a continuous area in
   memory long enough to store 5 numbers of float type, the numbers will
   reside here one after another.

   After doing this, we can index the array with square brackets ([ and ])
   like this: ARRAY_NAME[INDEX] where ARRAY_NAME is the name of the array
   (here vector) and INDEX is an expression that evaluates to integer,
   starting with 0 and going up to the vector length minus one (remember that
   programmers count from zero). So the first item of the array is at index
   0, the second at index 1 etc. The index can be a numeric constant like 3,
   but also a variable or a whole expression such as x + 3 * myFunction().
   Indexed array can be used just like any other variable, you can assign to
   it, you can use it in expressions etc. This is seen in the example. Trying
   to access an item beyond the array's bounds (e.g. vector[100]) will likely
   crash your program.

   Especially important are the parts of code staring with for (int i = 0; i
   < 5; ++i): this is an iteration over the array. It's a very common pattern
   that we use whenever we need to perform some action with every item of the
   array.

   Arrays can also be multidimensional, but we won't bothered with that right
   now.

   Why are arrays so important? They allow us to work with great number of
   data, not just a handful of numeric variables. We can create an array of
   million structs and easily work with all of them thanks to indexing and
   loops, this would be practically impossible without arrays. Imagine e.g. a
   game of [125]chess; it would be very silly to have 64 plain variables for
   each square of the board (squareA1, squareA2, ..., squareH8), it would be
   extremely difficult to work with such code. With an array we can represent
   the square as a single array, we can iterate over all the squares easily
   etc.

   One more thing to mention about arrays is how they can be passed to
   functions. A function can have as a parameter an array of fixed or unknown
   length. There is also one exception with arrays as opposed to other types:
   if a function has an array as parameter and the function modifies this
   array, the array passed to the function (the argument) will be modified as
   well (we say that arrays are passed by reference while other types are
   passed by value). We know this wasn't the case with other parameters such
   as int -- for these the function makes a local copy that doesn't affect
   the argument passed to the function. The following example shows what's
   been said:

 #include <stdio.h>

 // prints an int array of lengt 10
 void printArray10(int array[10])
 {
   for (int i = 0; i < 10; ++i)
     printf("%d ",array[i]);
 }

 // prints an int array of arbitrary lengt
 void printArrayN(int array[], int n)
 {
   for (int i = 0; i < n; ++i)
     printf("%d ",array[i]);
 }

 // fills an array with numbers 0, 1, 2, ...
 void fillArrayN(int array[], int n)
 {
   for (int i = 0; i < n; ++i)
     array[i] = i;
 }

 int main(void)
 {
   int array10[10];
   int array20[20];
  
   fillArrayN(array10,10);
   fillArrayN(array20,20);
    
   printArray10(array10);
   putchar('\n');
   printArrayN(array20,20);
    
   return 0;
 }

   The function printArray10 has a fixed length array as a parameter (int
   array[10]) while printArrayN takes as a parameter an array of unknown
   length (int array[]) plus one additional parameter to specify this length
   (so that the function knows how many items of the array it should print).
   The function printArray10 is important because it shows how a function can
   modify an array: when we call fillArrayN(array10,10); in the main
   function, the array array10 will be actually modified after when the
   function finishes (it will be filled with numbers 0, 1, 2, ...). This
   can't be done with other data types (though there is a trick involving
   [126]pointers which we will learn later).

   Now let's finally talk about text [127]strings. We've already seen strings
   (such as "hello"), we know we can print them, but what are they really? A
   string is a data type, and from C's point of view strings are nothing but
   arrays of chars (text characters), i.e. sequences of chars in memory. In C
   every string has to end with a 0 char -- this is NOT '0' (whose [128]ASCII
   value is 48) but the direct value 0 (remember that chars are really just
   numbers). The 0 char cannot be printed out, it is just a helper value to
   terminate strings. So to store a string "hello" in memory we need an array
   of length at least 6 -- one for each character plus one for the
   terminating 0. These types of string are called zero terminated strings
   (or C strings).

   When we write a string such as "hello" in our source, the C compiler
   creates an array in memory for us and fills it with characters 'h', 'e',
   'l', 'l', 'o', 0. In memory this may look like a sequence of numbers 104,
   101, 108, 108 111, 0.

   Why do we terminate strings with 0? Because functions that work with
   strings (such as puts or printf) don't know what length the string is. We
   can call puts("abc"); or puts("abcdefghijk"); -- the string passed to puts
   has different length in each case, and the function doesn't know this
   length. But thanks to these strings ending with 0, the function can
   compute the length, simply by counting characters from the beginning until
   it finds 0 (or more efficiently it simply prints characters until it finds
   0).

   The [129]syntax that allows us to create strings with double quotes (") is
   just a helper (syntactic sugar); we can create strings just as any other
   array, and we can work with them the same. Let's see an example:

 #include <stdio.h>

 int main(void)
 {
   char alphabet[27]; // 26 places for letters + 1 for temrinating 0
  
   for (int i = 0; i < 26; ++i)
     alphabet[i] = 'A' + i;
  
   alphabet[26] = 0; // terminate the string
  
   puts(alphabet);
  
   return 0;
 }

   alphabet is an array of chars, i.e. a string. Its length is 27 because we
   need 26 places for letters and one extra space for the terminating 0. Here
   it's important to remind ourselves that we count from 0, so the alphabet
   can be indexed from 0 to 26, i.e. 26 is the last index we can use, doing
   alphabet[27] would be an error! Next we fill the array with letters (see
   how we can treat chars as numbers and do 'A' + i). We iterate while i <
   26, i.e. we will fill all the places in the array up to the index 25
   (including) and leave the last place (with index 26) empty for the
   terminating 0. That we subsequently assign. And finally we print the
   string with puts(alphabet) -- here note that there are no double quotes
   around alphabet because its a variable name. Doing puts("alphabet") would
   cause the program to literally print out alphabet. Now the program
   outputs:

 ABCDEFGHIJKLMNOPQRSTUVWXYZ

   In C there is a standard library for working with strings called string
   (#include <string.h>), it contains such function as strlen for computing
   string length or strcmp for comparing strings.

   One final example -- a creature generator -- will show all the three new
   data types in action:

 #include <stdio.h>
 #include <stdlib.h> // for rand()

 typedef struct
 {
   char name[4]; // 3 letter name + 1 place for 0
   int weightKg;
   int legCount;
 } Creature; // some weird creature

 Creature creatures[100]; // global array of Creatures

 void printCreature(Creature c)
 {
   printf("Creature named %s ",c.name); // %s prints a string
   printf("(%d kg, ",c.weightKg);
   printf("%d legs)\n",c.legCount);
 }

 int main(void)
 {
   // generate random creatures:
  
   for (int i = 0; i < 100; ++i)
   {
     Creature c;
    
     c.name[0] = 'A' + (rand() % 26);
     c.name[1] = 'a' + (rand() % 26);
     c.name[2] = 'a' + (rand() % 26);
     c.name[3] = 0; // terminate the string

     c.weightKg = 1 + (rand() % 1000);
     c.legCount = 1 + (rand() % 10); // 1 to 10 legs

     creatures[i] = c;
   }
    
   // print the creatures:
  
   for (int i = 0; i < 100; ++i)
     printCreature(creatures[i]);
  
   return 0;
 }

   When run you will see a list of 100 randomly generated creatures which may
   start e.g. as:

 Creature named Nwl (916 kg, 4 legs)
 Creature named Bmq (650 kg, 2 legs)
 Creature named Cda (60 kg, 4 legs)
 Creature named Owk (173 kg, 7 legs)
 Creature named Hid (430 kg, 3 legs)
 ...

Macros/Preprocessor

   The C language comes with a feature called preprocessor which is necessary
   for some advanced things. It allows automatized modification of the source
   code before it is compiled.

   Remember how we said that compiler compiles C programs in several steps
   such as generating object files and linking? There is one more step we
   didn't mention: [130]preprocessing. It is the very first step -- the
   source code you give to the compiler first goes to the preprocessor which
   modifies it according to special commands in the source code called
   preprocessor directives. The result of preprocessing is a pure C code
   without any more preprocessing directives, and this is handed over to the
   actual compilation.

   The preprocessor is like a mini language on top of the C language, it has
   its own commands and rules, but it's much more simple than C itself, for
   example it has no data types or loops.

   Each directive begins with #, is followed by the directive name and
   continues until the end of the line (\ can be used to extend the directive
   to the next line).

   We have already encountered one preprocessor directive: the #include
   directive when we included library header files. This directive pastes a
   text of the file whose name it is handed to the place of the directive.

   Another directive is #define which creates so called [131]macro -- in its
   basic form a macro is nothing else than an alias, a nickname for some
   text. This is used to create constants. Consider the following code:

 #include <stdio.h>

 #define ARRAY_SIZE 10

 int array[ARRAY_SIZE];

 void fillArray(void)
 {
   for (int i = 0; i < ARRAY_SIZE; ++i)
     array[i] = i;
 }

 void printArray(void)
 {
   for (int i = 0; i < ARRAY_SIZE; ++i)
     printf("%d ",array[i]);
 }

 int main()
 {
   fillArray();
   printArray();
   return 0;
 }

   #define ARRAY_SIZE 10 creates a macro that can be seen as a constant named
   ARRAY_SIZE which stands for 10. From this line on any occurence of
   ARRAY_SIZE that the preprocessor encounters in the code will be replaced
   with 10. The reason for doing this is obvious -- we respect the [132]DRY
   (don't repeat yourself) principle, if we didn't use a constant for the
   array size and used the direct numeric value 10 in different parts of the
   code, it would be difficult to change them all later, especially in a very
   long code, there's a danger we'd miss some. With a constant it is enough
   to change one line in the code (e.g. #define ARRAY_SIZE 10 to #define
   ARRAY_SIZE 20).

   The macro substitution is literally a glorified copy-paste text
   replacement, there is nothing very complex going on. This means you can
   create a nickname for almost anything (for example you could do #define
   when if and then also use when in place of if -- but it's probably not a
   very good idea). By convention macro names are to be ALL_UPPER_CASE (so
   that whenever you see an all upper case word in the source code, you know
   it's a macro).

   Macros can optionally take parameters similarly to functions. There are no
   data types, just parameter names. The usage is demonstrated by the
   following code:

 #include <stdio.h>

 #define MEAN3(a,b,c) (((a) + (b) + (c)) / 3)

 int main()
 {
   int n = MEAN3(10,20,25);
  
   printf("%d\n",n);
    
   return 0;
 }

   MEAN3 computes the mean of 3 values. Again, it's just text replacement, so
   the line int n = MEAN3(10,20,25); becomes int n = (((10) + (20) + (25)) /
   3); before code compilation. Why are there so many brackets in the macro?
   It's always good to put brackets over a macro and all its parameters
   because the parameters are again a simple text replacement; consider e.g.
   a macro #define HALF(x) x / 2 -- if it was invoked as HALF(5 + 1), the
   substitution would result in the final text 5 + 1 / 2, which gives 5
   (instead of the intended value 3).

   You may be asking why would we use a macro when we can use a function for
   computing the mean? Firstly macros don't just have to work with numbers,
   they can be used to generate parts of the source code in ways that
   functions can't. Secondly using a macro may sometimes be simpler, it's
   shorter and will be faster to execute because the is no function call
   (which has a slight overhead) and because the macro expansion may lead to
   the compiler precomputing expressions at compile time. But beware: macros
   are usually worse than functions and should only be used in very justified
   cases. For example macros don't know about data types and cannot check
   them, and they also result in a bigger compiled executable (function code
   is in the executable only once whereas the macro is expanded in each place
   where it is used and so the code it generates multiplies).

   Another very useful directive is #if for conditional inclusion or
   exclusion of parts of the source code. It is similar to the C if command.
   The following example shows its use:

 #include <stdio.h>

 #define RUDE 0

 void printNumber(int x)
 {
   puts(
 #if RUDE
     "You idiot, the number is:"
 #else
     "The number is:"
 #endif
   );
  
   printf("%d\n",x);
 }

 int main()
 {
   printNumber(3);
   printNumber(100);
  
 #if RUDE
   puts("Bye bitch.");
 #endif
    
   return 0;
 }

   When run, we get the output:

 The number is:
 3
 The number is:
 100

   And if we change #define RUDE 0 to #define RUDE 1, we get:

 You idiot, the number is:
 3
 You idiot, the number is:
 100
 Bye bitch.

   We see the #if directive has to have a corresponding #endif directive that
   terminates it, and there can be an optional #else directive for an else
   branch. The condition after #if can use similar operators as those in C
   itself (+, ==, &&, || etc.). There also exists an #ifdef directive which
   is used the same and checks if a macro of given name has been defined.

   #if directives are very useful for conditional compilation, they allow for
   creation of various "settings" and parameters that can fine-tune a program
   -- you may turn specific features on and off with this directive. It is
   also helpful for [133]portability; compilers may automatically define
   specific macros depending on the platform (e.g. _WIN64, __APPLE__, ...)
   based on which you can trigger different code. E.g.:

 #ifdef _WIN64
   puts("Your OS sucks.");
 #endif

   Let us talk about one more thing that doesn't fall under the preprocessor
   language but is related to constants: enumerations. Enumeration is a data
   type that can have values that we specify individually, for example:

 typedef enum
 {
   APPLE,
   PEAR,
   TOMATO
 } Fruit;

   This creates a new data type Fruit. Variables of this type may have values
   APPLE, PEAR or TOMATO, so we may for example do Fruit myFruit = APPLE;.
   These values are in fact integers and the names we give them are just
   nicknames, so here APPLE is equal to 0, PEAR to 1 and TOMATO to 2.

Pointers

   Pointers are an advanced topic that many people fear -- many complain
   they're hard to learn, others complain about memory unsafety and potential
   dangers of using pointers. These people are stupid, pointers are great.

   But beware, there may be too much new information in the first read. Don't
   get scared, give it some time.

   Pointers allow us to do certain advanced things such as allocate dynamic
   memory, return multiple values from functions, inspect content of memory
   or use functions in similar ways in which we use variables.

   A [134]pointer is essentially nothing complicated: it is a data type that
   can hold a memory address (plus an information about what data type should
   be stored at that address). An address is simply a number. Why can't we
   just use an int to store a memory address? Because the size of int and a
   pointer may differ, the size of pointer depends on each platform's address
   width. Besides this, as said, a pointer actually holds not only an address
   but also the information about the type it points to, which is a safety
   mechanism that will become clear later. It is also good when the compiler
   knows a certain variable is supposed to point to a memory rather than to
   hold a generic number -- this can all prevent bugs. I.e. pointers and
   generic integers are distinguished for the same reason other data types
   are distinguished -- in theory they don't have to be distinguished, but
   it's safer.

   It is important to stress again that a pointer is not a pure address but
   it also knows about the data type it is pointing to, so there are many
   kinds of pointers: a pointer to int, a pointer to char, a pointer to a
   specific struct type etc.

   A variable of pointer type is created similarly to a normal variable, we
   just add * after the data type, for example int *x; creates a variable
   named x that is a pointer to int (some people would write this as int*
   x;).

   But how do we assign a value to the pointer? To do this, we need an
   address of something, e.g. of some variable. To get an address of a
   variable we use the & character, i.e. &a is the address of a variable a.

   The last basic thing we need to know is how to [135]dereference a pointer.
   Dereferencing means accessing the value at the address that's stored in
   the pointer, i.e. working with the pointed to value. This is again done
   (maybe a bit confusingly) with * character in front of a pointer, e.g. if
   x is a pointer to int, *x is the int value to which the pointer is
   pointing. An example can perhaps make it clearer.

 #include <stdio.h>

 int main(void)
 {
   int normalVariable = 10;
   int *pointer;
  
   pointer = &normalVariable;
  
   printf("address in pointer: %p\n",pointer);
   printf("value at this address: %d\n",*pointer);
  
   *pointer = *pointer + 10;
  
   printf("normalVariable: %d\n",normalVariable);
  
   return 0;
 }

   This may print e.g.:

 address in pointer: 0x7fff226fe2ec
 value at this address: 10
 normalVariable: 20

   int *pointer; creates a pointer to int with name pointer. Next we make the
   pointer point to the variable normalVariable, i.e. we get the address of
   the variable with &normalVariable and assign it normally to pointer. Next
   we print firstly the address in the pointer (accessed with pointer) and
   the value at this address, for which we use dereference as *pointer. At
   the next line we see that we can also use dereference for writing to the
   pointed address, i.e. doing *pointer = *pointer + 10; here is the same as
   doing normalVariable = normalVariable + 10;. The last line shows that the
   value in normalVariable has indeed changed.

   IMPORTANT NOTE: You generally cannot read and write from/to random
   addresses! This will crash your program. To be able to write to a certain
   address it must be [136]allocated, i.e. reserved for use. Addresses of
   variables are allocated by the compiler and can be safely operated with.

   There's a special value called NULL (a macro defined in the standard
   library) that is meant to be assigned to pointer that points to "nothing".
   So when we have a pointer p that's currently not supposed to point to
   anything, we do p = NULL;. In a safe code we should always check (with if)
   whether a pointer is not NULL before dereferencing it, and if it is, then
   NOT dereference it. This isn't required but is considered a "good
   practice" in safe code, storing NULL in pointers that point nowhere
   prevents dereferencing random or unallocated addresses which would crash
   the program.

   But what can pointers be good for? Many things, for example we can kind of
   "store variables in variables", i.e. a pointer is a variable which says
   which variable we are now using, and we can switch between variable any
   time. E.g.:

 #include <stdio.h>

 int bankAccountMonica = 1000;
 int bankAccountBob = -550;
 int bankAccountJose = 700;

 int *payingAccount; // pointer to who's currently paying

 void payBills(void)
 {
   *payingAccount -= 200;
 }

 void buyFood(void)
 {
   *payingAccount -= 50;
 }

 void buyGas(void)
 {
   *payingAccount -= 20;
 }

 int main(void)
 {
   // let Jose pay first
  
   payingAccount = &bankAccountJose;
  
   payBills();
   buyFood();
   buyGas();
    
   // that's enough, now let Monica pay

   payingAccount = &bankAccountMonica;

   buyFood();
   buyGas();
   buyFood();
   buyFood();
    
   // now it's Bob's turn
  
   payingAccount = &bankAccountBob;
  
   payBills();
   buyFood();
   buyFood();
   buyGas();
    
   printf("Monika has $%d left.\n",bankAccountMonica);
   printf("Jose has $%d left.\n",bankAccountJose);
   printf("Bob has $%d left.\n",bankAccountBob);
    
   return 0;
 }

   Well, this could be similarly achieved with arrays, but pointers have more
   uses. For example they allow us to return multiple values by a function.
   Again, remember that we said that (with the exception of arrays) a
   function cannot modify a variable passed to it because it always makes its
   own local copy of it? We can bypass this by, instead of giving the
   function the value of the variable, giving it the address of the variable.
   The function can read the value of that variable (with dereference) but it
   can also CHANGE the value, it simply writes a new value to that address
   (again, using dereference). This example shows it:

 #include <stdio.h>
 #include <math.h>

 #define PI 3.141592

 // returns 2D coordinates of a point on a unit circle
 void getUnitCirclePoint(float angle, float *x, float *y)
 {
   *x = sin(angle);
   *y = cos(angle);
 }

 int main(void)
 {
   for (int i = 0; i < 8; ++i)
   {
     float pointX, pointY;
    
     getUnitCirclePoint(i * 0.125 * 2 * PI,&pointX,&pointY);
    
     printf("%lf %lf\n",pointX,pointY);
   }
    
   return 0;
 }

   Function getUnitCirclePoint doesn't return any value in the strict sense,
   but thank to pointers it effectively returns two float values via its
   parameters x and y. These parameters are of the data type pointer to float
   (as there's * in front of them). When we call the function with
   getUnitCirclePoint(i * 0.125 * 2 * PI,&pointX,&pointY);, we hand over the
   addresses of the variables pointX and pointY (which belong to the main
   function and couldn't normally be accessed in getUnitCirclePoint). The
   function can then compute values and write them to these addresses (with
   dereference, *x and *y), changing the values in pointX and pointY,
   effectively returning two values.

   Now let's take a look at pointers to structs. Everything basically works
   the same here, but there's one thing to know about, a [137]syntactic sugar
   known as an arrow (->). Example:

 #include <stdio.h>

 typedef struct
 {
   int a;
   int b;
 } SomeStruct;

 SomeStruct s;
 SomeStruct *sPointer;

 int main(void)
 {
   sPointer = &s;
  
   (*sPointer).a = 10; // without arrow
   sPointer->b = 20;   // same as (*sPointer).b = 20
    
   printf("%d\n",s.a);
   printf("%d\n",s.b);
    
   return 0;
 }

   Here we are trying to write values to a struct through pointers. Without
   using the arrow we can simply dereference the pointer with *, put brackets
   around and access the member of the struct normally. This shows the line
   (*sPointer).a = 10;. Using an arrow achieves the same thing but is perhaps
   a bit more readable, as seen in the line sPointer->b = 20;. The arrow is
   simply a special shorthand and doesn't need any brackets.

   Now let's talk about arrays -- these are a bit special. The important
   thing is that an array is itself basically a pointer. What does this mean?
   If we create an array, let's say int myArray[10];, then myArray is
   basically a pointer to int in which the address of the first array item is
   stored. When we index the array, e.g. like myArray[3] = 1;, behind the
   scenes there is basically a dereference because the index 3 means: 3
   places after the address pointed to by myArray. So when we index an array,
   the compiler takes the address stored in myArray (the address of the array
   start) and adds 3 to it (well, kind of) by which it gets the address of
   the item we want to access, and then dereferences this address.

   Arrays and pointer are kind of a duality -- we can also use array indexing
   with pointers. For example if we have a pointer declared as int *x;, we
   can access the value x points to with a dereference (*x), but ALSO with
   indexing like this: x[0]. Accessing index 0 simply means: take the value
   stored in the variable and add 0 to it, then dereference it. So it
   achieves the same thing. We can also use higher indices (e.g. x[10]), BUT
   ONLY if x actually points to a memory that has at least 11 allocated
   places.

   This leads to a concept called [138]pointer arithmetic. Pointer arithmetic
   simply means we can add or subtract numbers to pointer values. If we
   continue with the same pointer as above (int *x;), we can actually add
   numbers to it like *(x + 1) = 10;. What does this mean?! It means exactly
   the same thing as x[1]. Adding a number to a pointer shifts that pointer
   given number of places forward. We use the word places because each data
   type takes a different space in memory, for example char takes one byte of
   memory while int takes usually 4 (but not always), so shifting a pointer
   by N places means adding N times the size of the pointed to data type to
   the address stored in the pointer.

   This may be a lot information to digest. Let's provide an example to show
   all this in practice:

 #include <stdio.h>

 // our own string print function
 void printString(char *s)
 {
   int position = 0;
  
   while (s[position] != 0)
   {
     putchar(s[position]);
     position += 1;
   }
 }

 // returns the length of string s
 int stringLength(char *s)
 {
   int length = 0;
    
   while (*s != 0) // count until terminating 0
   {
     length += 1;
     s += 1; // shift the pointer one character to right
   }
  
   return length;
 }

 int main(void)
 {
   char testString[] = "catdog";
  
   printString("The string '");
   printString(testString);
   printString("' has length ");
  
   int l = stringLength(testString);
  
   printf("%d.",l);

   return 0;
 }

   The output is:

 The string 'catdog' has length 6.

   We've created a function for printing strings (printString) similar to
   puts and a function for computing the length of a string (stringLength).
   They both take as an argument a pointer to char, i.e. a string. In
   printString we use indexing ([ and ]) just as if s was an array, and
   indeed we see it works! In stringLength we similarly iterate over all
   characters in the string but we use dereference (*s) and pointer
   arithmetic (s += 1;). It doesn't matter which of the two styles we choose
   -- here we've shown both, for educational purposes. Finally notice that
   the string we actually work with is created in main as an array with char
   testString[] = "catdog"; -- here we don't need to specify the array size
   between [ and ] because we immediately assign a string literal to it
   ("catdog") and in such a case the compiler knows how big the array needs
   to be and automatically fills in the correct size.

   Now that know about pointers, we can finally completely explain the
   functions from stdio we've been using:

     * int puts(char *s): A simple and fast function for printing a string
       (adds the newline character \n at the end).
     * int printf(char *format, ...): A little bit more complex function that
       can print not only strings but also other data types. It takes a
       variable number of parameters. The first one is always a string that
       specifies the print format -- this string can contain special
       sequences that will be replaced by textual representations of values
       we additionally provide as extra parameters after format. E.g. the
       sequence "%d" is replaced with a number obtained from the value of a
       corresponding int parameter. Similarly %c is for char, %s for strings,
       %p for pointers. Example: printf("MyInt = %d, myChar = %c, MyStr =
       %s\n",myInt,myChar,myStr);.
     * int getchar(void): Reads a single text character from the input and
       returns it. Why does the function return int and not char? Because the
       function can return additional special values such as EOF (end of
       file) which couldn't be stored in plain char.
     * int scanf(char *format, ...): Function for reading various data types
       from the input. Like printf it takes a variable number of parameters.
       The first one is a string that specifies which data type(s) to read --
       this is a bit complicated but "%d" reads an int, "%f" float, "%c" char
       and "%s" string. The following arguments are pointers to expected data
       types, so e.g. if we've provided the format string "%d", a pointer to
       int has to follow. Through this parameter the value that's been read
       will be returned (in the same way we've seen in one example above).

Files

   Now we'll take a look at how we can read and write from/to files on the
   computer disk which enables us to store information permanently or
   potentially process data such as images or audio. Files aren't so
   difficult.

   We work with files through functions provided in the stdio library (so it
   has to be included). We distinguish two types of files:

     * text files: Contain text, are human readable.
     * binary files: Contain binary data, aren't human readable, are more
       efficient but also more prone to corruption.

   From programmer's point of view there's actually not a huge difference
   between the two, they're both just sequences of characters or bytes (which
   are kind of almost the same). Text files are a little more abstract, they
   handle potentially different format of newlines etc. The main thing for us
   is that we'll use slightly different functions for each type.

   There is a special data type for file called FILE (we'll be using a
   pointer to it). Whatever file we work with, we need to firstly open it
   with the function fopen and when we're done with it, we need to close it
   with a function fclose.

   First we'll write something to a text file:

 #include <stdio.h>

 int main(void)
 {
   FILE *textFile = fopen("test.txt","w"); // "w" for write

   if (textFile != NULL) // if opened successfully
     fprintf(textFile,"Hello file.");
   else
     puts("ERROR: Couldn't open file.");

   fclose(textFile);

   return 0;
 }

   When run, the program should create a new file named test.txt in the same
   directory we're in and in it you should find the text Hello file.. FILE
   *textFile creates a new variable textFile which is a pointer to the FILE
   data type. We are using a pointer simply because the standard library is
   designed this way, its functions work with pointers (it can be more
   efficient). fopen("test.txt","w"); attempts to open the file test.txt in
   text mode for writing -- it returns a pointer that represents the opened
   file. The mode, i.e. text/binary, read/write etc., is specified by the
   second argument: "w"; w simply specifies write and the text mode is
   implicit (it doesn't have to be specified). if (textFile != NULL) checks
   if the file has been successfully opened; the function fopen returns NULL
   (the value of "point to nothing" pointers) if there was an error with
   opening the file (such as that the file doesn't exist). On success we
   write text to the file with a function fprintf -- it's basically the same
   as printf but works on files, so it's first parameter is always a pointer
   to a file to which it should write. You can of course also print numbers
   and anything that printf can with this function. Finally we mustn't forget
   to close the file at the end with fclose!

   Now let's write another program that reads the file we've just created and
   writes its content out in the command line:

 #include <stdio.h>

 int main(void)
 {
   FILE *textFile = fopen("test.txt","r"); // "r" for read

   if (textFile != NULL) // if opened successfully
   {
     char c;

     while (fscanf(textFile,"%c",&c) != EOF) // while not end of file
       putchar(c);
   }
   else
     puts("ERROR: Couldn't open file.");

   fclose(textFile);

   return 0;
 }

   Notice that in fopen we now specify "r" (read) as a mode. Again, we check
   if the file has been opened successfully (if (textFile != NULL)). If so,
   we use a while loop to read and print all characters from the file until
   we encounter the end of file. The reading of file characters is done with
   the fscanf function inside the loop's condition -- there's nothing
   preventing us from doing this. fscanf again works the same as scanf (so it
   can read other types than only chars), just on files (its first argument
   is the file to read from). On encountering end of file fscanf returns a
   special value EOF (which is macro constant defined in the standard
   library). Again, we must close the file at the end with fclose.

   We will now write to a binary file:

 #include <stdio.h>

 int main(void)
 {
   unsigned char image[] = // image in ppm format
   {
     80, 54, 32, 53, 32, 53, 32, 50, 53, 53, 32,
     255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
     255,255,255,    0, 0,  0, 255,255,255,   0,  0,  0, 255,255,255,
     255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
       0,  0,  0, 255,255,255, 255,255,255, 255,255,255,   0,  0,  0,
     255,255,255,   0,  0,  0,   0,  0,  0,   0,  0,  0, 255,255,255 
   };

   FILE *binFile = fopen("image.ppm","wb");

   if (binFile != NULL) // if opened successfully
     fwrite(image,1,sizeof(image),binFile);
   else
     puts("ERROR: Couldn't open file.");

   fclose(binFile);

   return 0;
 }

   Okay, don't get scared, this example looks complex because it is trying to
   do a cool thing: it creates an image file! When run, it should produce a
   file named image.ppm which is a tiny 5x5 smiley face image in [139]ppm
   format. You should be able to open the image in any good viewer (I
   wouldn't bet on [140]Windows programs though). The image data was made
   manually and are stored in the image array. We don't need to understand
   the data, we just know we have some data we want to write to a file.
   Notice how we can manually initialize the array with values using { and }
   brackets. We open the file for writing and in binary mode, i.e. with a
   mode "wb", we check the success of the action and then write the whole
   array into the file with one function call. The function is name fwrite
   and is used for writing to binary files (as opposed to fprintf for text
   files). fwrite takes these parameters: pointer to the data to be written
   to the file, size of one data element (in bytes), number of data elements
   and a pointer to the file to write to. Our data is the image array and
   since "arrays are basically pointers", we provide it as the first
   argument. Next argument is 1 (unsigned char always takes 1 byte), then
   length of our array (sizeof is a special operator that substitutes the
   size of a variable in bytes -- since each item in our array takes 1 byte,
   sizeof(image) provides the number of items in the array), and the file
   pointer. At the end we close the file.

   And finally we'll finish with reading this binary file back:

 #include <stdio.h>

 int main(void)
 {
   FILE *binFile = fopen("image.ppm","rb");

   if (binFile != NULL) // if opened successfully
   {
     unsigned char byte;

     while (fread(&byte,1,1,binFile))
       printf("%d ",byte);

     putchar('\n');
   }
   else
     puts("ERROR: Couldn't open file.");

   fclose(binFile);

   return 0;
 }

   The file mode is now "rb" (read binary). For reading from binary files we
   use the fread function, similarly to how we used fscanf for reading from a
   text file. fread has these parameters: pointer where to store the read
   data (the memory must have sufficient space allocated!), size of one data
   item, number of items to read and the pointer to the file which to read
   from. As the first argument we pass &byte, i.e. the address of the
   variable byte, next 1 (we want to read a single byte whose size in bytes
   is 1), 1 (we want to read one byte) and the file pointer. fread returns
   the number of items read, so the while condition holds as long as fread
   reads bytes; once we reach end of file, fread can no longer read anything
   and returns 0 (which in C is interpreted as a false value) and the loop
   ends. Again, we must close the file at the end.

More On Functions (Recursion, Function Pointers)

   There's more to be known about functions.

   An important concept in programming is [141]recursion -- the situation in
   which a function calls itself. Yes, it is possible, but some rules have to
   be followed.

   When a function calls itself, we have to ensure that we won't end up in
   infinite recursion (i.e. the function calls itself which subsequently
   calls itself and so on until infinity). This crashes our program. There
   always has to be a terminating condition in a recursive function, i.e. an
   if branch that will eventually stop the function from calling itself
   again.

   But what is this even good for? Recursion is actually very common in math
   and programming, many problems are recursive in nature. Many things are
   beautifully described with recursion (e.g. [142]fractals). But remember:
   anything a recursion can achieve can also be achieved by iteration (loop)
   and vice versa. It's just that sometimes one is more elegant or more
   computationally efficient.

   Let's see this on a typical example of the mathematical function called
   [143]factorial. Factorial of N is defined as N x (N - 1) x (N - 2) x ... x
   1. It can also be defined recursively as: factorial of N is 1 if N is 0,
   otherwise N times factorial of N - 1. Here is some code:

 #include <stdio.h>

 unsigned int factorialRecursive(unsigned int x)
 {
   if (x == 0) // terminating condition
     return 1;
   else
     return x * factorialRecursive(x - 1);
 }

 unsigned int factorialIterative(unsigned int x)
 {
   unsigned int result = 1;
    
   while (x > 1)
   {
     result *= x;
     x--; 
   }
  
   return result;
 }

 int main(void)
 {
   printf("%d %d\n",factorialRecursive(5),factorialIterative(5));
   return 0;
 }

   factorialIterative computes the factorial by iteration. factorialRecursive
   uses recursion -- it calls itself. The important thing is the recursion is
   guaranteed to end because every time the function calls itself, it passes
   a decremented argument so at one point the function will receive 0 in
   which case the terminating condition (if (x == 0)) will be triggered which
   will avoid the further recursive call.

   It should be mentioned that performance-wise recursion is almost always
   worse than iteration (function calls have certain overhead), so in
   practice it is used sparingly. But in some cases it is very well justified
   (e.g. when it makes code much simpler while creating unnoticeable
   performance loss).

   Another thing to mention is that we can have pointers to functions; this
   is an advanced topic so we'll stay at it just briefly. Function pointers
   are pretty powerful, they allow us to create so called [144]callbacks:
   imagine we are using some [145]GUI framework and we want to tell it what
   should happen when a user clicks on a specific button -- this is usually
   done by giving the framework a pointer to our custom function that it will
   be called by the framework whenever the button is clicked.

Dynamic Allocation (Malloc)

   Dynamic memory allocation means the possibility of reserving additional
   memory ([146]RAM) for our program at run time, whenever we need it. This
   is opposed to static memory allocation, i.e. reserving memory for use at
   compile time (when compiling, before the program runs). We've already been
   doing static allocation whenever we created a variable -- compiler
   automatically reserves as much memory for our variables as is needed. But
   what if we're writing a program but don't yet know how much memory it will
   need? Maybe the program will be reading a file but we don't know how big
   that file is going to be -- how much memory should we reserve? Dynamic
   allocation allows us to reserve this memory with functions when the
   program is actually runing and already knows how much of it should be
   reserved.

   It must be known that dynamic allocation comes with a new kind of bug
   known as a [147]memory leak. It happens when we reserve a memory and
   forget to free it after we no longer need it. If this happens e.g. in a
   loop, the program will continue to "grow", eat more and more RAM until
   operating system has no more to give. For this reason, as well as others
   such as simplicity, it may sometimes be better to go with only static
   allocation.

   Anyway, let's see how we can allocate memory if we need to. We use mostly
   just two functions that are provided by the stdlib library. One is malloc
   which takes as an argument size of the memory we want to allocate
   (reserve) in bytes and returns a pointer to this allocated memory if
   successful or NULL if the memory couldn't be allocated (which in serious
   programs we should always check). The other function is free which frees
   the memory when we no longer need it (every allocated memory should be
   freed at some point) -- it takes as the only parameter a pointer to the
   memory we've previously allocated. There is also another function called
   realloc which serves to change the size of an already allocated memory: it
   takes a pointer the the allocated memory and the new size in byte, and
   returns the pointer to the resized memory.

   Here is an example:

 #include <stdio.h>
 #include <stdlib.h>

 #define ALLOCATION_CHUNK 32 // by how many bytes to resize

 int main(void)
 {
   int charsRead = 0;
   int resized = 0; // how many times we called realloc
   char *inputChars = malloc(ALLOCATION_CHUNK * sizeof(char)); // first allocation

   while (1) // read input characters
   {
     char c = getchar();
 
     charsRead++;

     if ((charsRead % ALLOCATION_CHUNK) == 0)
     {
       inputChars = // we need more space, resize the array
         realloc(inputChars,(charsRead / ALLOCATION_CHUNK + 1) * ALLOCATION_CHUNK * sizeof(char));
        
       resized++;
     }

     inputChars[charsRead - 1] = c;
   
     if (c == '\n')
     {
       charsRead--; // don't count the last newline character
       break;
     }
   }
  
   puts("The string you entered backwards:");
  
   while (charsRead > 0)
   {
     putchar(inputChars[charsRead - 1]);
     charsRead--;
   }

   free(inputChars); // important!
  
   putchar('\n');
   printf("I had to resize the input buffer %d times.",resized);
    
   return 0;
 }

   This code reads characters from the input and stores them in an array
   (inputChars) -- the array is dynamically resized if more characters are
   needed. (We restrain from calling the array inputChars a string because we
   never terminate it with 0, we couldn't print it with standard functions
   like puts.) At the end the entered characters are printed backwards (to
   prove we really stored all of them), and we print out how many times we
   needed to resize the array.

   We define a constant (macro) ALLOCATION_CHUNK that says by how many
   characters we'll be resizing our character buffer. I.e. at the beginning
   we create a character buffer of size ALLOCATION_CHUNK and start reading
   input character into it. Once it fills up we resize the buffer by another
   ALLOCATION_CHUNK characters and so on. We could be resizing the buffer by
   single characters but that's usually inefficient (the function malloc may
   be quite complex and take some time to execute).

   The line starting with char *inputChars = malloc(... creates a pointer to
   char -- our character buffer -- to which we assign a chunk of memory
   allocated with malloc. Its size is ALLOCATION_CHUNK * sizeof(char). Note
   that for simplicity we don't check if inputChars is not NULL, i.e. whether
   the allocation succeeded -- but in your program you should do it :) Then
   we enter the character reading loop inside which we check if the buffer
   has filled up (if ((charsRead % ALLOCATION_CHUNK) == 0)). If so, we used
   the realloc function to increase the size of the character buffer. The
   important thing is that once we exit the loop and print the characters
   stored in the buffer, we free the memory with free(inputChars); as we no
   longer need it.

Debugging, Optimization

   [148]Debugging means localizing and fixing [149]bugs (errors) in your
   program. In practice there are always bugs, even in very short programs
   (you've probably already figured that out yourself), some small and
   insignificant and some pretty bad ones that make your program unusable,
   vulnerable or even dangerous.

   There are two kinds of bugs: [150]syntactic errors and [151]semantic
   errors. A syntactic error is when you write something not obeying the C
   grammar, it's like a typo or grammatical error in a normal language --
   these errors are very easy to detect and fix, a compiler won't be able to
   understand your program and will point you to the exact place where the
   error occurs. A semantic error can be much worse -- it's a logical error
   in the program; the program will compile and run but the program will
   behave differently than intended. The program may crash, leak memory, give
   wrong results, run slowly, corrupt files etc. These errors may be hard to
   spot and fix, especially when they happen in rare situations. We'll be
   only considering semantic errors from now on.

   If we spot a bug, how do we fix it? The first thing is to find a way to
   replicate it, i.e. find the exact steps we need to make with the program
   to make the bug appear (e.g. "in the menu press keys A and B
   simultaneously", ...). Next we need to trace and locate which exact line
   or piece of code is causing the bug. This can either be done with the help
   of specialized [152]debuggers such as [153]gdb or [154]valgrind, but
   there's usually a much easier way of using printing functions such as
   printf. (Still do check out the above mentioned debuggers, they're very
   helpful.)

   Let's say your program crashes and you don't know at which line. You
   simply put prints such as printf("A\n"); and printf("B\n); at the
   beginning and end of a code you suspect might be causing the crash. Then
   you run the program: if A is printed but B isn't, you know the crash
   happened somewhere between the two prints, so you shift the B print a
   little bit up and so on until you find exactly after which line B stops
   printing -- this is the line that crashes the program. IMPORTANT NOTE: the
   prints have to have newline (\n) at the end, otherwise this method may not
   work because of output buffering.

   Of course, you may use the prints in other ways, for example to detect at
   which place a value of variable changes to a wrong value. ([155]Asserts
   are also good for keeping an eye on correct values of variables.)

   What if the program isn't exactly crashing but is giving wrong results?
   Then you need to trace the program step by step (not exactly line by line,
   but maybe function by function) and check which step has a problem in it.
   If for example your game AI is behaving stupid, you firstly check (with
   prints) if it correctly detects its circumstances, then you check whether
   it makes the correct decision based on the circumstances, then you check
   whether the pathfinding algorithm finds the correct path etc. At each step
   you need to know what the correct behavior should be and you try to find
   where the behavior is broken.

   Knowing how to fix a bug isn't everything, we also need to find the bugs
   in the first place. [156]Testing is the process of trying to find bugs by
   simply running and using the program. Remember, testing can't prove there
   are no bugs in the program, it can only prove bugs exist. You can do
   testing manually or automate the tests. Automated tests are very important
   for preventing so called [157]regressions (so the tests are called
   regression tests). Regression happens when during further development you
   break some of its already working features (it is very common, don't think
   it won't be happening to you). Regression test (which can simply be just a
   normal C program) simply automatically checks whether the already
   implemented functions still give the same results as before (e.g. if
   sin(0) = 0 etc.). These tests should be run and pass before releasing any
   new version of the program (or even before any commit of new code).

   [158]Optimization is also a process of improving an already working
   program, but here we try to make the program more efficient -- the most
   common goal is to make the program faster, smaller or consume less
   [159]RAM. This can be a very complex task, so we'll only mention it
   briefly.

   The very basic thing we can do is to turn on automatic optimization with a
   compiler flag: -O3 for speed, -Os for program size (-O2 and -O1 are less
   aggressive speed optimizations). Yes, it's that simple, you simply add -O3
   and your program gets magically faster. Remember that optimizations
   against different resources are often antagonistic, i.e. speeding up your
   program typically makes it consume more memory and vice versa. You need to
   choose. Optimizing manually is a great art. Let's suppose you are
   optimizing for speed -- the first, most important thing is to locate the
   part of code that's slowing down you program the most, so called
   [160]bottleneck. That is the code you want to make faster. Trying to
   optimize non-bottlenecks doesn't speed up your program as a whole much;
   imagine you optimize a part of the code that takes 1% of total execution
   time by 200% -- your program will only get 0.5% faster. Bottlenecks can be
   found using [161]profiling -- measuring the execution time of different
   parts of the program (e.g. each function). This can be done manually or
   with tools such a [162]gprof. Once you know where to optimize, you try to
   apply different techniques: using algorithms with better [163]time
   complexity, using [164]look up tables, optimizing [165]cache behavior and
   so on. This is beyond the scope of this tutorial.

Final Program

   Now is the time to write a final program that showcases what we've
   learned, so let's write a quite simple but possibly useful [166]hex
   viewer. The program will allow us to interactively inspect bytes in any
   file, drawing their hexadecimal values along with their addresses,
   supporting one character commands to move within the file. If you want,
   you can take it and improve it as an exercise, for example by adding more
   viewing modes (showing decimal octal or ASCII values), maybe even allowing
   editing and saving the file. Here is the source code:

 /* Simple interactive hex file viewer. */

 #include <stdio.h>
 #include <stdlib.h>

 #define ROWS 10 // how many rows and columns to print at one screen
 #define COLS 16

 unsigned char *fileContent = NULL;   // this will contain the loaded file
 unsigned long long fileSize = 0;     // size of fileContent in bytes
 unsigned long long fileOffset = 0;   // current offset within the file
 const char *fileName = NULL;

 // Loads file with given name into fileContent, returns 1 on success, 0 on fail.
 int loadFile(const char *fileToOpen)
 {
   FILE *file = fopen(fileToOpen,"rb");

   if (file == NULL)
     return 0;

   fseek(file,0L,SEEK_END); // get to the end of the file
   fileSize = ftell(file);  // our position now says the size of the file
   rewind(file);            // get back to start of the file

   fileContent = malloc(fileSize);  // allocate memory to load the file into

   if (fileContent == NULL)
   {
     fclose(file); // don't forget to close the file
     return 0;
   }

   if (fread(fileContent,1,fileSize,file) != fileSize)
   {
     fclose(file);
     free(fileContent);
     return 0;
   }

   fclose(file);

   return 1;
 }

 // Call when loaded file is no longer needed.
 void unloadFile(void)
 {
   free(fileContent); // free the allocated memory
 }

 // Draws the current screen, i.e. hex view of the file at current offset.
 void drawScreen(void)
 {
   for (int i = 0; i < 80; ++i) // scroll the old screen our of the view
     putchar('\n');

   printf("%s: %llu / %llu\n\n",fileName,fileOffset,fileSize);

   unsigned long long offset = fileOffset;

   for (int i = 0; i < ROWS * COLS; ++i)
   {
     if (offset % COLS == 0)
       printf("%04X    ",(int) offset);

     if (offset < fileSize)
       printf("%02X ",fileContent[offset]);
     else
       printf(".. ");

     offset++;

     if (offset % COLS == 0) // break line after each COLS values
       putchar('\n');
   }
 }

 int main(int argc, char **argv)
 {
   if (argc < 2)
   {
     puts("ERROR: please pass a file to open");
     return 1;
   }

   fileName = argv[1]; // (argv[0] is the name of our program, we want argv[1])

   if (!loadFile(fileName))
   {
     printf("ERROR: couldn't open the file \"%s\"\n",fileName);
     return 1;
   }

   int goOn = 1;

   while (goOn) // the main interactive loop
   {
     drawScreen();

     puts("\ntype command (w = end, s = start, a = back, d = next, q = quit)");

     char userInput = getchar();

     switch (userInput)
     {
       case 'q':
         goOn = 0;
         break;

       case 's':
         if (fileOffset + COLS < fileSize)
           fileOffset += COLS;

           break;

       case 'w':
         if (fileOffset >= COLS)
           fileOffset -= COLS;
  
         break;

       case 'a':
         fileOffset = 0;
         break;

       case 'd':
         fileOffset = ((fileSize - COLS) / COLS) * COLS; // aligns the offset
         break;

       default:
         puts("unknown command, sorry");
         break;
     }
   }

   unloadFile();

   return 0;
 }

   To add a few comments: the program opens a file whose name it gets passed
   as a command line argument, so it is used as: ./hexview myfile. We try to
   correctly perform all safety checks, e.g. if we actually get passed the
   file name, if we manage to open it and so on. Our program (a bit
   inefficiently) loads the whole file into memory (advanced programs only
   load parts of the file) -- for this it first checks the file size,
   allocates sufficient memory for it with malloc (also checking for errors)
   and loads it there. Then we have a function to draw the current file view
   and inside the main program body we have an interactive loop that loads
   and handles user commands and issues the view drawing. That is basically
   it!

Bonus: Introduction To Graphics (ASCII, PPM, SDL2, ...)

   Let's stress you should only get into graphics after you've written
   several purely command-line programs and are comfortable with the
   language. Don't try graphics programming until you can easily work with 2D
   arrays, structs and so on. [167]Graphics is a huge topic of its own, there
   is so much we can't cover here, remember this is just a quick, basic
   starting point for making pictures with C.

   For start please note that:

     * C itself doesn't know anything about graphics. C is just trying to be
       a good programming language, it leaves the vast area of graphics for
       others to solve, therefore though you can try to avoid it (see below),
       typically you will use a third party [168]library to draw some real
       pixels to the screen, there isn't a universal way of doing it, you
       have to choose specific solution based on what you want to achieve,
       what's available etc.
     * By graphics we really just mean drawing [169]pixels. Things like
       keyboard and mouse [170]input (which you need for anything
       [171]interactive like [172]games), loading [173]PNG pictures, playing
       sounds, loading and displaying 3D models, detecting [174]collisions of
       virtual objects and so on won't necessarily be covered here, it's all
       too much to learn at once. We will ONLY be trying to show basic shapes
       on the screen.
     * We'll be doing things in simplified ways here, omitting common
       [175]optimizations, safety checks and so on. Just know that in
       practice things will be yet a bit more complex.

   So, how to actually do graphics? As said, graphics is a super wide topic,
   there is no [176]silver bullet, all depends on what we really need.
   Consider the following:

     * Need to quickly draw something quite basic (e.g. a graph)? [177]Keep
       it simple and just use [178]ASCII art. You can draw simple pictures to
       the console with ASCII art, i.e. you emulate real screen pixels with
       text characters. This is a nice, natural transition from text to
       graphics when studying programming, so you may start with this. The
       disadvantage is you can only draw very simple, rough and low
       resolution pictures, usually without colors, but you can animate them
       and make your program a little bit interactive. By doing things
       yourself you'll also get an idea what graphics is about and will
       better understand why libraries you'll use later work the way they do.
       A big advantage is that ASCII art graphics can be done without any
       library (there are libraries like [179]ncurses, but you probably won't
       need them) and will keep your program quite simple, nice and
       [180]portable. You can use this for simple visualization, animations,
       games and so on.
     * Need to just produce one or two static pictures (e.g. function plot)?
       Output a picture file. You can make a C program that will simply save
       a picture to a file which you can open in any image viewer. For this
       you can use quite simple libraries but it is also possible to load and
       save simple formats without any libraries at all! You can very easily
       export bitmap images (e.g. [181]PPM, [182]farbfeld, [183]bmp ...) as
       well as beautiful [184]vector images (e.g. by exporting [185]SVG) with
       curves, [186]antialiasing, fancy fonts and so on, you can auto-convert
       them with other tools to other formats and so on. This will suffice
       for many things like data visualizations, function plots, photo
       processing, even 3D rendering, while keeping your program highly
       [187]portable, i.e. it will be usable everywhere, even on computers
       without any GUI or screen, it will be much less [188]bloated.
     * Need a fast, real time interactive program (e.g. a game)? Use a
       [189]library for that. If you want the "real deal", i.e. interactive,
       fully colorful high-res graphics, e.g. for a serious game, you'll
       typically have to use a library -- in C this library is traditionally
       [190]SDL2 (but there are many alternatives, e.g. [191]SFML,
       [192]Allegro, [193]SAF, ...). This is a bit more complex, so only go
       this way if you really must -- you have to install the library, learn
       to use it and your program will become more bloated, less portable,
       bigger in size, harder to compile and so on.

   We will show an example of each of these approaches further on.

   But first let's quickly mention what graphics programming at this level is
   essentially about, i.e. the kind of "workflow" we'll always try to
   implement:

     * The most essential thing is basically to be able to draw a [194]pixel,
       i.e. set a [195]color of one point in the picture. Once you can draw a
       single pixel, you can draw anything, just like to build any kind of
       house you have to be able to lay bricks -- every shape is just some
       formation of pixels that you can construct with C code: a [196]line is
       just a series of pixels one next to another, [197]cricle is a curved
       line, rectangle is just area filled with pixels of some color and so
       on. So at the beginning we'll just have some way of drawing a single
       pixel. Typically this can be e.g. a function drawPixel(x,y,color) --
       graphic libraries will normally offer you a function like this,
       letting you draw pixels without actually caring about what magic is
       going on inside the function. (Sometimes you will also encounter a
       lower level way in which the library maps a screen to memory and you
       will draw pixels by literally writing values to memory, i.e. with
       pointers or arrays.)
     * With the basic pixel drawing function we'll draw our picture however
       we want -- if we're using a library, there may be helper functions and
       of course we can write our own functions too, for example
       drawLine(fromX,fromY,toX,toY,color), drawText(x,y,text,size,color) and
       so on. The picture itself is just a virtual canvas, a computer memory
       holding numbers, typically a two dimensional [198]array whose values
       are manipulated by the drawPixel function. At this point we are doing
       nothing else than changing values in memory.
     * At the end, once drawing is complete, we have to show (present) the
       picture. This is to say that when we're drawing, the picture isn't
       actually seen, it is only changing in memory, it is shown to the user
       only when it's completed, i.e. when we issue a special command such as
       drawingDone(). Why can't the picture just be shown at all times? In
       theory it can, but you encounter problems, imagine e.g. a game that
       quickly redraws the picture on the screen -- here the user would see
       flickering, he might even see enemies show briefly behind a wall
       before the wall is actually drawn and so on. So a way to solve this is
       to do the drawing off screen and only at the end say "now we're done
       drawing, show the image" (for more details see [199]double buffering).
     * Also note that usually there is some kind of management around graphic
       code, i.e. some initialization of the program's window, setting its
       resolution, allocation of memory for the screen pixels, setting the
       pixel formats, [200]callbacks and so on. Similarly at the end you
       often have to clean things up and as many graphic systems are based on
       events, you have to periodically check events like key presses, window
       resizes etc. Interactive programs will furthermore have an infinite
       loop (so called game loop) in which they check events, redraw the
       screen, wait for a while (to keep the right [201]FPS) and so on.
       Libraries try to do many thing for you but you have to at least tell
       them some very basic things. So be prepared for a lot extra code.

   Now let's finally do this. We'll set up some basic code for drawing a
   rectangle and try to draw it with different approaches.

   The ASCII approach:

 #include <stdio.h>

 #define SCREEN_WIDTH 60
 #define SCREEN_HEIGHT 25

 char screen[SCREEN_WIDTH * SCREEN_HEIGHT]; // our virtual screen

 // sets a single pixel at given coordinates
 void drawPixel(int x, int y, char pixel)
 {
   int index = y * SCREEN_WIDTH + x;

   if (index >= 0 && index < SCREEN_WIDTH * SCREEN_HEIGHT)
     screen[index] = pixel;
 }

 // presents the drawn picture on the screen
 void drawScreen(void)
 {
   for (int i = 0; i < 30; ++i) // shift old picture out of view
     putchar('\n');

   const char *p = screen;

   for (int y = 0; y < SCREEN_HEIGHT; ++y)
   {
     for (int x = 0; x < SCREEN_WIDTH; ++x)
     {
       putchar(*p);
       p++;
     }

     putchar('\n');
   }
 }

 // fills rectangle with given pixel value
 void drawRectangle(int x, int y, int width, int height, char pixel)
 {
   for (int j = 0; j < height; ++j)
     for (int i = 0; i < width; ++i)
       drawPixel(x + i,y + j,pixel);
 }

 int main(void)
 {
   int quit = 0;
   int playerX = SCREEN_WIDTH / 2, playerY = SCREEN_HEIGHT / 2;

   while (!quit) // main game loop
   {
     drawRectangle(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,'.'); // clear screen with dots
     drawRectangle(playerX - 2,playerY - 1,5,3,'X');    // draw player
     drawScreen();                                      // present the picture

     puts("enter command (w/s/a/d/q):");
     char input = getchar();

     switch (input)
     {
       case 'w': playerY--; break;
       case 's': playerY++; break;
       case 'a': playerX--; break;
       case 'd': playerX++; break;
       case 'q': quit = 1; break;
     }
   }

   return 0;
 }

   With this we have a simple interactive program that draws a dotted screen
   with rectangle that represents the player, you can compile it like any
   other program, it uses no external libraries. User can move the rectangle
   around by typing commands. There is a main infinite loop (this is the
   above mentioned game loop, a typical thing in interactive applications) in
   which we read the user commands and redraw the picture on the screen.
   Notice we have our basic drawPixel function as well as the drawScreen
   function for presenting the finished picture, we also have a helper
   drawRectangle function. The screen array represents our virtual picture
   (it is declared as one dimensional array but in reality it is treated as
   two dimensional by the setPixel function). As an exercise you can try to
   draw other simple shapes, for example horizontal and vertical lines,
   non-filled rectangles -- if you're brave enough you can also try a filled
   circle (hint: points inside a circle mustn't be further away from the
   center than the circle radius).

   Now let's try to do something similar, but this time creating a "real
   picture" made of true pixels, exported to a file:

 #include <stdio.h>

 #define SCREEN_WIDTH 640   // picture resolution
 #define SCREEN_HEIGHT 480

 unsigned char screen[SCREEN_WIDTH * SCREEN_HEIGHT * 3]; // screen, 3 is for RGB

 // sets a single pixel at given coordinates
 void drawPixel(int x, int y, int red, int green, int blue)
 {
   int index = y * SCREEN_WIDTH + x;

   if (index >= 0 && index < SCREEN_WIDTH * SCREEN_HEIGHT)
   {
     index *= 3;
     screen[index] = red;
     screen[index + 1] = green;
     screen[index + 2] = blue;
   }
 }

 // outputs the image in PPM format
 void outputPPM(void)
 {
   printf("P6 %d %d 255\n",SCREEN_WIDTH,SCREEN_HEIGHT); // PPM file header

   for (int i = 0; i < SCREEN_WIDTH * SCREEN_HEIGHT * 3; ++i)
     putchar(screen[i]);
 }

 // fills rectangle with given pixel
 void drawRectangle(int x, int y, int width, int height, int red, int green,
   int blue)
 {
   for (int j = 0; j < height; ++j)
     for (int i = 0; i < width; ++i)
       drawPixel(x + i,y + j,red,green,blue);
 }

 int main(void)
 {
   drawRectangle(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,128,128,128); // clear with grey
   drawRectangle(SCREEN_WIDTH / 2 - 32, SCREEN_HEIGHT / 2 - 32,64,64,255,0,0);
   outputPPM();
   return 0;
 }

   Wow, this is yet simpler! Although we have no interactivity now, we get a
   nice picture of a red rectangle on grey background, and don't even need
   any library (not even the file library!). We just compile this and save
   the program output to a file, e.g. with ./program > picture.ppm. The
   picture we get is stored in [202]PPM format -- a very simple format that
   basically just stores raw [203]RGB values and can be opened in many
   viewers and editors (e.g. [204]GIMP). Notice the similar functions like
   drawPixel -- we only have a different parameter for the pixel (in ASCII
   example it was a single ASCII character, now we have 3 color values: red,
   green and blue). In the main program we also don't have any infinite loop,
   the program is non-interactive.

   And now finally to the more complex example of a fully interactive graphic
   using SDL2:

 #include <SDL2/SDL.h> // include SDL library

 #define SCREEN_WIDTH 640
 #define SCREEN_HEIGHT 480

 #define COLOR_WHITE 0xff // some colors in RGB332 format
 #define COLOR_RED 0xe0

 unsigned char _SDL_screen[SCREEN_WIDTH * SCREEN_HEIGHT];
 SDL_Window *_SDL_window;
 SDL_Renderer *_SDL_renderer;
 SDL_Texture *_SDL_texture;
 const unsigned char *_SDL_keyboardState;
 int sdlEnd;

 static inline void drawPixel(unsigned int x, unsigned int y, unsigned char color)
 {
   if (x < SCREEN_WIDTH && y < SCREEN_HEIGHT)
     _SDL_screen[y * SCREEN_WIDTH + x] = color;
 }

 void sdlStep(void)
 {
   SDL_Event event;

   SDL_UpdateTexture(_SDL_texture,NULL,_SDL_screen,SCREEN_WIDTH);
   SDL_RenderClear(_SDL_renderer);
   SDL_RenderCopy(_SDL_renderer,_SDL_texture,NULL,NULL);
   SDL_RenderPresent(_SDL_renderer);

   while (SDL_PollEvent(&event))
     if (event.type == SDL_QUIT)
       sdlEnd = 1;

   SDL_Delay(10); // relieve CPU for 10 ms
 }

 void sdlInit(void)
 {
   SDL_Init(0);
   _SDL_window = SDL_CreateWindow("program",SDL_WINDOWPOS_UNDEFINED,
     SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH,SCREEN_HEIGHT,SDL_WINDOW_SHOWN);
   _SDL_renderer = SDL_CreateRenderer(_SDL_window,-1,0);
   _SDL_texture = SDL_CreateTexture(_SDL_renderer,SDL_PIXELFORMAT_RGB332,
     SDL_TEXTUREACCESS_STATIC,SCREEN_WIDTH,SCREEN_HEIGHT);
   _SDL_keyboardState = SDL_GetKeyboardState(NULL);
   SDL_PumpEvents();
 }

 void sdlDestroy(void)
 {
   SDL_DestroyTexture(_SDL_texture);
   SDL_DestroyRenderer(_SDL_renderer);
   SDL_DestroyWindow(_SDL_window);
 }

 int sdlKeyPressed(int key)
 {
   return _SDL_keyboardState[key];
 }

 void drawRectangle(int x, int y, int width, int height, unsigned char color)
 {
   for (int j = 0; j < height; ++j)
     for (int i = 0; i < width; ++i)
       drawPixel(x + i,y + j,color);
 }

 int main(void)
 {
   int playerX = SCREEN_WIDTH / 2, playerY = SCREEN_HEIGHT / 2;

   sdlInit();

   while (!sdlEnd) // main loop
   {
     sdlStep(); // redraws screen, refreshes keyboard etc.

     drawRectangle(0,0,SCREEN_WIDTH,SCREEN_HEIGHT,COLOR_WHITE);
     drawRectangle(playerX - 10,playerY - 10,20,20,COLOR_RED); // draw player

     // update player position:
     if (sdlKeyPressed(SDL_SCANCODE_D))
       playerX++;
     else if (sdlKeyPressed(SDL_SCANCODE_A))
       playerX--;
     else if (sdlKeyPressed(SDL_SCANCODE_W))
       playerY--;
     else if (sdlKeyPressed(SDL_SCANCODE_S))
       playerY++;
   }

   sdlDestroy();

   return 0;
 }

   This program creates a window with a rectangle that can be moved with the
   WSAD keys. To compile it you first need to install the SDL2 library -- how
   to do this depends on your system (just look it up somewhere; on Debian
   like systems this will typically be done with sudo apt-get install
   libsdl2-dev), and then you also need to link SDL2 during compilation, e.g.
   like this: gcc -O3 -o graphics_sdl2 -lSDL2 graphics_sdl2.c.

   This code is almost a bare minimum template for SDL that doesn't even
   perform any safety checks such as validating creation of each SDL object
   (which in real code SHOULD be present, here we left it out for better
   clarity). Despite this the code is quite long with a lot of
   [205]boilerplate; that's because we need to initialize a lot of stuff, we
   have to create a graphical window, a texture to which we will draw, we
   have to tell SDL the format in which we'll represent our pixels, we also
   have to handle operating system events so that we get the key presses, to
   know when the window is closed and so on. Still in the end we are working
   with essentially the same functions, i.e. we have drawPixel (this time
   with pixel as a single char value because we are using the simple [206]332
   format) and drawRectangle. This time sdlStep is the function that presents
   the drawn image on screen (it also does other things like handling the SDL
   events and pausing for a while to not heat up the CPU).

Where To Go Next

   We haven't nearly covered the whole of C, but you should have pretty solid
   basics now. Now you just have to go and write a lot of C programs, that's
   the only way to truly master C. WARNING: Do not start with an ambitious
   [207]project such as a 3D game. You won't make it and you'll get
   demotivated. Start very simple (a Tetris clone perhaps?). Try to develop
   some consistent programming style/formatting -- see our [208]LRS
   programming style you may adopt (it's better than trying to make your own
   really).

   See also supplemental articles at the beginning of this tutorial.

   You should definitely learn about common [209]data structures ([210]linked
   lists, [211]binary trees, [212]hash tables, ...) and [213]algorithms
   ([214]sorting, [215]searching, ...). As an advanced programmer you should
   definitely know a bit about [216]memory management. Also take a look at
   basic [217]licensing. Another thing to learn is some [218]version control
   system, preferably [219]git, because this is how we manage bigger programs
   and how we collaborate on them. To start making graphical programs you
   should get familiar with some library such as [220]SDL.

   A great amount of experience can be gained by contributing to some
   existing project, collaboration really boosts your skill and knowledge of
   the language. This should only be done when you're at least intermediate.
   Firstly look up a nice project on some git hosting site, then take a look
   at the bug tracker and pick a bug or feature that's easy to fix or
   implement (low hanging fruit).

Links:
1. c.md
2. programming_language.md
3. source_code.md
4. cli.md
5. c.md
6. algorithm.md
7. programming_tips.md
8. programming_style.md
9. debugging.md
10. exercises.md
11. c_pitfalls.md
12. memory_management.md
13. optimization.md
14. saf.md
15. sdl.md
16. c.md
17. programming_language.md
18. algorithm.md
19. compiled.md
20. interpreted.md
21. compiler.md
22. native.md
23. low_level.md
24. abstraction.md
25. garbage_collection.md
26. pointer.md
27. endianness.md
28. imperative.md
29. oop.md
30. bloat.md
31. bullshit.md
32. modern.md
33. python.md
34. javascript.md
35. package_manager.md
36. debugger.md
37. build_system.md
38. module.md
39. generics.md
40. garbage_collection.d
41. oop.md
42. hashmap.md
43. list.md
44. type_inference.md
45. modern.md
46. compiler.md
47. gcc.md
48. text_editor.md
49. plain_text.md
50. syntax.md
51. vim.md
52. gedit.md
53. geany.md
54. ide.md
55. rich_text.md
56. libreoffice.md
57. shit.md
58. compiler.md
59. gcc.md
60. clang.md
61. tcc.md
62. unix.md
63. gnu.md
64. linux.md
65. c99.md
66. syntax.md
67. variable.md
68. ram.md
69. keyword.md
70. data_type.md
71. pointer.md
72. expression.md
73. syntax.md
74. algorithm.md
75. control_structure.md
76. branch.md
77. loop.md
78. syntax.md
79. and.md
80. or.md
81. not.md
82. syntax.md
83. pointer.md
84. game.md
85. seed.md
86. function.md
87. sqrt.md
88. side_effect.md
89. dry.md
90. quadratic_equation.md
91. library.md
92. sine.md
93. sdl.md
94. data_type.md
95. recursion.md
96. forward_decl.md
97. local_variable.md
98. sugar.md
99. undefined_behavior.md
100. increment.md
101. decrement.md
102. ternary_operator.md
103. operand.md
104. global_variable.md
105. float.md
106. real_number.md
107. cast.md
108. forward_decl.md
109. unix.md
110. vector.md
111. implementation.md
112. header_file.md
113. pi.md
114. object_file.md
115. linker.md
116. build_system.md
117. make.md
118. cmake.md
119. header_only.md
120. debugging.md
121. primitive_type.md
122. compound_type.md
123. struct.md
124. array.md
125. chess.md
126. pointer.md
127. string.md
128. ascii.md
129. syntax.md
130. preprocessing.md
131. macro.md
132. dry.md
133. portability.md
134. pointer.md
135. dereference.md
136. allocation.md
137. sugar.md
138. pointer_arithmetic.md
139. ppm.md
140. windows.md
141. recursion.md
142. fractal.md
143. factorial.md
144. callback.md
145. gui.md
146. ram.md
147. memory_leak.md
148. debugging.md
149. bug.md
150. syntax.md
151. semantics.md
152. debugger.md
153. gdb.md
154. valgrind.md
155. assert.md
156. testing.md
157. regression.md
158. optimization.md
159. ram.md
160. bottleneck.md
161. profiling.md
162. gprof.md
163. time_complexity.md
164. lut.md
165. cache.md
166. hex_editor.md
167. graphics.md
168. library.md
169. pixel.md
170. io.md
171. interactivity.md
172. game.md
173. png.md
174. collision.md
175. optimization.md
176. silver_bullet.md
177. kiss.md
178. ascii_art.md
179. ncurses.md
180. portability.md
181. ppm.md
182. farbfeld.md
183. bmp.md
184. vector.md
185. svg.md
186. antialiasing.md
187. portability.md
188. bloat.md
189. library.md
190. sdl.md
191. sfml.md
192. allegro.md
193. saf.md
194. pixel.md
195. color.md
196. line.md
197. circle.md
198. array.md
199. double_buffering.md
200. callback.md
201. fps.md
202. ppm.md
203. rgb.md
204. gimp.md
205. boilerplate.md
206. rgb332.md
207. project.md
208. programming_style.md
209. data_strucutre.md
210. linked_list.md
211. binary_tree.md
212. hash.md
213. algorithm.md
214. sorting.md
215. search.md
216. memory_management.md
217. license.md
218. vcs.md
219. git.md
220. sdl.md