class: center, middle ### COMP26020 Programming Languages and Paradigms Part 1: C Programming *** # Functions ??? - Hello everyone, in this short video I will introduce functions in C --- # Functions - They have a **name**, zero or more **parameters** with **types**, and a **return type** - Like variables functions must be declared before being used ```c int add_two_integers(int a, int b) { int result = a + b; return result; } int main() { int x = 1; int y = 2; int sum = add_two_integers(x, y); printf("result: %d", sum); if(add_two_integers(x, y)) printf(" (non zero)\n"); else printf(" (zero)\n"); return 0; } ``` .codelink[
`07-functions/function.c`
] ??? - Functions have a name, zero or more parameters -- each with a type and a name, and a return type - In this example we have a function named add two integers - It takes two integers as parameters named a and b - It returns an integer which is the sum of the two parameters - Like variables, functions must be declared before being called. - We declare the function by first writing the return value type, then the function name, followed by the parameters list between parentheses, each with its type - We can call a function as presented in the example, passing the parameter values between parentheses - The call evaluates to the function return value so we can affect a variable with it or use as a condition --- # Functions - The absence of return value can be indicated with the `void` type ```c void print_hello(void) { printf("hello!\n"); return; // we can even omit this as the function does not return anything } int main() { print_hello(); return 0; } ``` .codelink[
`07-functions/function-return-void.c`
] ??? - If your function does not return anything, set void as the return type - Here it's the case for the print hello function --- # Function Calls .center[**Function parameters and return value are passed as copies**] ```c void my_function(int parameter) { parameter = 12; // does not update x in main } int main() { int x = 10; my_function(x); printf("x is %d\n", x); // prints 10 return 0; } ``` .codelink[
`07-functions/function-parameters.c`
] ??? - An important thing to note is that in C, function parameters are passed by copy and not by reference as it is the case in other languages such as Python - What this means is that each function call gets its own local copy of the parameters' values and updating will not modify the calling context - In the example we have x set to 10, then passed as a parameter of a function that sets this parameter to 12 - If we print the value of x after the function call it is still 12 because the function, when called, got his own copy of the value of x - We will see in a later lecture how to have a function update a variable from the calling context (through pointers) --- # Forward Declarations ```c #include
/* Forward declaration, also called function _prototype_ */ int add(int a, int b); int main(int argc, char **argv) { int a = 1; int b = 2; /* Here we need the function to be at least declared -- not necessarily defined */ printf("%d + %d = %d\n", a, b, add(a, b)); return 0; } /* The actual function definition */ int add(int a, int b) { return a + b; } ``` .codelink[
`07-functions/forward-declaration.c`
] - The compiler parses source files from top to bottom - One can declare a function before 1) using it and 2) defining it ??? - The function **signature** or **prototype** suffices for the declaration - As shown on the example it contains the function return type, name, parameters, and simply ends with a semicolon - The body can be declared further in the file - Including below lines of code where the function is called - This is called a **forward declaration** - It gives you more freedom for organising your code --- # Variables Scope and Lifetime - **Global** variables declared outside functions - visible at the level of the entire source file ```c int global_var; void add_to_global_var(int value) { global_var = global_var + value; } int main() { global_var = 100; add_to_global_var(50); printf("global_var is %d\n", global_var); return 0; } ``` - Try to limit the use of globals as much as possible - A lot of global state makes it harder to reason about the program - More info why globals are dangerous: [https://bit.ly/3iE0M2Y](https://bit.ly/3iE0M2Y) ??? - Until now we only saw **local** variables visible only from within the context they are declared in - It can be a function, a loop body, etc. - On the contrary **global** variables are declared outside functions - They can be read or written from everywhere in the sources - For example here global_var is set to 100 and printed in main, and it is also incremented in the add to global var function - Now there are many issues with global variables - An important one is that because they can be read or written from anywhere they make it harder to understand and reason about the program - So you should only use them when needed --- # Variables Scope and Lifetime - Within a function, a declared local variable is accessible within its enclosing braces (a *block* of code) .leftcol[ ```c int x = 12; if(x) { int y = 14; printf("inner block, x: %d\n", x); printf("inner block, y: %d\n", y); } printf("outer block, x: %d\n", x); // ERROR -- y only visible in the if body: // printf("outer block, y: %d\n", y); ``` ] .rightcol[ ```c for(int i=0; i<10; i++) { printf("In loop body, i is %d\n", i); } // ERROR -- i only visible in loop body // printf("Out of loop body, i is %d\n", i); int j; for(j=0; j<10; j++) { printf("In loop body, j is %d\n", j); } // WORKING -- j declared in current block printf("Out of loop body, j is %d\n", j); // ``` .codelink[
`07-functions/variable-scope-lifetime.c`
] ] - It is good practice for clarity to declare local variables at the beginning of their block ??? - Contrary to globals, local variables are visible only within the enclosing block of code, delimited with braces - Let's have a look at this example - While x visible from anywhere in main, y cannot be printed there because it's visible only within the if body - The i iterator here is visible only in the for loop body. - For j, because it is declared in the scope of main, it is still visible after the loop finishes - Generally, it is good practice to try to declare local variable at the beginning of the block --- # Summary - Functions - Global vs. Local variables ---- .center[Feedback form: https://bit.ly/3jD6dRc]
??? - So let's recap - We saw how to declare, define, and call functions - And we also talked about global and local variables - In the next video we will see how to create custom data structure