# C Tutorial This is a relatively quick WIP [C](c.md) tutorial. You should probably know at least the completely basic ideas of programming before reading this (what's a [programming language](programming_language.md), [source code](source_code.md), [command line](cli.md) etc.). If you're as far as already knowing another language, this should be pretty easy to understand. ## About C and Programming [C](c.md) is - A **[programming language](programming_language.md)**, i.e. a language that lets you express [algorithms](algorithm.md). - [Compiled](compiled.md) language (as opposed to [interpreted](interpreted.md)), i.e. you have to compile the code you write (with [compiler](compiler.md)) in order to obtain a [native](native.md) executable program (a binary file that you can run directly). - Extremely **fast and efficient**. - Very **widely supported and portable** to almost anything. - **[Low level](low_level.md)**, i.e. there is relatively little [abstraction](abstraction.md) and not many comfortable built-in functionality such as [garbage collection](garbage_collection.md), you have to write many things yourself, you will deal with [pointers](pointer.md), [endianness](endianness.md) etc. - Considered **hard**, but in certain ways it's simple, it lacks [bloat](bloat.md) and [bullshit](bullshit.md) of "[modern](modern.md)" languages which is an essential thing. It will take long to learn 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. Programming in C works like this: 1. You write a C source code into a file. 2. You compile the file with a C [compiler](compiler.md) such as [gcc](gcc.md) (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 [text editor](text_editor.md); any [plain text](plain_text.md) editor will do but you should use some that can highlight C [syntax](syntax.md) -- this helps very much when programming and is practically a necessity. Ideal editor is [vim](vim.md) but it's a bit difficult to learn so you can use something as simple as [Gedit](gedit.md) or [Geany](geany.md). We do NOT recommend using huge programming [IDEs](ide.md) such as "VS Code" and whatnot. You definitely can NOT use an advanced document editor that can format text such as [LibreOffice](libreoffice.md) or that [shit](shit.md) from Micro$oft, this won't work because it's not plain text. Next you'll need a C [compiler](compiler.md), the program that will turn your source code into a runnable program. We'll use the most commonly used one called [gcc](gcc.md) (you can try different ones such as [clang](clang.md) or [tcc](tcc.md) if you want). If you're on a [Unix](unix.md)-like system such as [GNU](gnu.md)/[Linux](linux.md) (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 [C99](c99.md), 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 // 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 ` tells the compiler we want to include a library named *stdio* (the weird [syntax](syntax.md) 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 withing 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 // 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 **[variable](variable.md) is a place in memory which has a name**. 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 [RAM](ram.md), 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 [keywords](keyword.md) 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 **[data type](data_type.md)**; 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 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. 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 **[expressions](expression.md)**. 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 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 [syntax](syntax.md) 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 [algorithms](algorithm.md), it's not enough to just write linear sequences of commands. Two things (called [control structures](control_structure.md)) are very important to have in addition: - **[branches](branch.md)**: 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"**. - **[loops](loop.md)** (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 [syntax](syntax.md) 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 hold, 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 means false, anything 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 [AND](and.md)): yields 1 if both operands are non-0, otherwise 0. - `||` (logical [OR](or.md)): yields 1 if at least one operand is non-0, otherwise 0. - `!` (logical [NOT](not.md)): 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 [syntax](syntax.md) 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 [pointers](pointer.md)). 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 < 10` (not `i <= 10`). 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 [game](game.md): 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 #include #include 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 `, `#include `: 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 [seed](seed.md) 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. **[Function](function.md) 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 [square root](sqrt.md), 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 **[side effects](side_effect.md)**; things done besides computing and 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 [DRY](dry.md) (*Don't Repeat Yourself*) principle -- this is extremely important in programming. Imagine you need to solve a [quadratic equation](quadratic_equation.md) 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 **[libraries](library.md)** -- 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 [sine](sine.md), or [SDL](sdl.md), 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 and well as in Kelvin: ``` #include 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 [data type](data_type.md) 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 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 `n`s 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 function 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`), it 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 return 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 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 [recursion](recursion.md)), but only those that have been defined before them in the source code (this can be fixed with so called [forward declarations](forward_decl.md)). 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 void writeFactors(int x) // writes divisord 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 **[local variable](local_variable.md)** 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. ## Additional Details (Global, Switch, Float, Forward Decls, ...) 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 [syntactic sugar](sugar.md): 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 [undefined behavior](undefined_behavior.md). 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 **[incrementing](increment.md)** and **[decrementing](decrement.md)**. This just means adding/substracting 1. In C there is a pretty unique operator called the **[ternary operator](ternary_operator.md)** (ternary for having three [operands](operand.md)). 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 `if`s. For example instead of ``` if (x >= 10) x -= 10; else x = 10; ``` we can write ``` x = x >= 10 ? x - 10 : 10; ``` **[Global variables](global_variable.md)**: 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 #include // 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) { 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`: [Floating point](float.md) number (`double` is bigger and more precise than `float`) -- an approximation of [real numbers](real_number.md), i.e. numbers with a fractional part such as 2.5 or 0.0001. 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 **[forward declaractions](forward_decl.md)** -- 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 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). ## 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 **[implementation](implementation.md)** of algorithms, i.e. code that translates into actual program instructions. These files are what's handed to the compiler. - *.h files*, or **[header files](header_file.md)**: 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 [pi](pi.md). 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 [object file](object_file.md) 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 **[linker](linker.md)** 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 ` -- 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 #include "library.h" int main(void) { int n = square(5); printf("%d\n",n); return 0; } ``` 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 **[build systems](build_system.md)**, they are for example [Make](make.md) and [Cmake](cmake.md). 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 [header-only libraries](header_only.md), 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 [debugging](debugging.md). ## Advanced Data Types and Variables (Structs, Arrays) ## Macros/Preprocessor ## Pointers ## More on Functions (Recursion, Function Pointers) ## Dynamic Allocation (Malloc) ## Debugging, Optimization ## Advanced Stuff ## Under The Hood