class: center, middle ### COMP26020 Programming Languages and Paradigms Part 1: C Programming *** # Variables, Types, Printing to the Console --- class: middle, center, inverse # Variables --- name: variables # Variables ```c #include
int main() { int a; // declare local variable a of type int (signed integer) a = 12; // set the value of a to 12 printf("a's value: %d\n", a); // print the value of a return 0; } ``` .codelink[
`04-c-variables-types-printf/variables-1.c`
] - Variable: **name**, **type**, **value** - Must be **declared** before being used - Declare with `
;` --- template: variables ```c int _x; // variable names must start with a letter or an underscore int sum; int final_balance2; // they can contain any combination of letters, digits and underscores int a_long_variable_name_is_also_possible_but_not_very_practical; ``` --- template: variables .leftcol[ ```c int a; int b; int c; int d = 12; // declare and set int x, y = 10, z = 11; // declare x, y and z, // set y and z a = 12; // set a to 12 ``` ] .rightcol[ ```c b = 20; // set b to 20 c = 10 + 10; // set c to 20 a = b; // a = 20 d++; // d = d + 1 y *= 2; // y = y * 2 // ``` .codelink[
`04-c-variables-types-printf/variables-2.c`
] ] --- class: middle, inverse, center # Types --- # Types The compiler uses types for 2 things: - At build time, the compiler **checks the validity of operations** on the variable based on its type - The type defines the **amount of memory** the compiler allocates for a variable -- .center[**3 basic type categories: integers, floating-point numbers, characters**] --- # Types: Memory Storage ```c int a; // an int (signed integer) takes 4 bytes in memory on x86-64 a = -12345; ``` At runtime:
--- # Types Characters and floats: ```c char my_char_variable; float my_float_variable; my_char_variable = 'x'; // single quotes for character constants my_float_variable = 12.4; ``` --- # Types Arithmetic mixing integers and floats: ```c int int1 = 2, int2 = 4; float float1 = 2.8; /* when mixed with floats in arithmetic, integers are converted to float */ float float_res = int1 + float1; // float_res: 4.8 float float_res2 = int1 * (float1 + int2); // float_res2: 13.6 /* when stored in an integer variable, floats are _truncated_ (towards zero) */ int int_res = int1 + float1; // int_res: 4 printf("float result: %f\n", float_res); printf("float result2: %f\n", float_res2); printf("integer result: %d\n", int_res); ``` .codelink[
`04-c-variables-types-printf/types.c`
] --- # More Types, Modifiers - Types: `char`, `int`, `float` (single precision), `double` (double precision) - Integer **modifiers**: - `unsigned`: variable stores only non-negative integers - `short` for (potentially) less memory space, `long` for (potentially) more memory space ```c short int a; // signed, at least 16 bits: [−32,767, +32,767] int b; // signed, at least 16 bits: [−32,767, +32,767] unsigned int c; // unsigned: [0, +65,535] long int d; // at least 32 bits: [−2,147,483,647, +2,147,483,647] unsigned long int e; // unsigned: [0, +4,294,967,295] long long int f; // at least 64 bits: [-9x10^18, +9x10^18] long long unsigned int g; // unsigned: [0, +18x10^18] float h; // storage size unspecified, generally 32 bits double i; // storage size unspecified, generally 64 bits ``` - Exact sizes are **implementation-defined**: they depend on the architecture and compiler - Complete list here: https://en.wikipedia.org/wiki/C_data_types ??? - When declaring a variable, we use a type combined with optional modifiers, which together define what the variable can hold and how much space is reserved. - It is very important to be aware of the storage size of your variables, as things like overflows can have very nasty consequences. - Here are a few examples, with what the C standard guarantees about the corresponding storage sizes. - For example, int is signed and must be at least 16 bits (2 bytes), so it can store at least the numbers from about minus 32 thousand to plus 32 thousand. - Unsigned int has the same size but is unsigned, so it can store larger positive numbers and no negative ones. - Note that the storage sizes given by the standard are rather imprecise: only minimums are specified. - The actual sizes are implementation-defined: they depend on the target CPU architecture and the compiler. --- # Types: Storage Size in Memory - Use `sizeof` to get the exact size of a type on a given machine: ```c int so_short = sizeof(short int); int so_int = sizeof(int); int so_uint = sizeof(unsigned int); int so_long = sizeof(long int); int so_longlong = sizeof(long long int); int so_float = sizeof(float); int so_double = sizeof(double); printf("size of short: %d bytes\n", so_short); printf("size of int: %d bytes\n", so_int); printf("size of unsigned int: %d bytes\n", so_uint); printf("size of long int: %d bytes\n", so_long); printf("size of long long int: %d bytes\n", so_longlong); printf("size of float: %d bytes\n", so_float); printf("size of double: %d bytes\n", so_double); ``` .codelink[
`04-c-variables-types-printf/sizeof.c`
]
??? - To get the exact storage size we can use the sizeof operator, which can be applied to a type (or to an expression). - We can compile and run it like this, and we see that: - the size of short is 2 bytes - the sizes of int, unsigned int and float are 4 bytes - the sizes of long int, long long int and double are 8 bytes. - So in memory these variables look somewhat like this. - 2 bytes for the short, 4 for the int, and so on. --- class: center, middle, inverse # Printing to the Console: printf ??? - We have been using printf to print many things to the console; let's see how it works in more detail. --- # Printing to the Console - `printf` accepts **one or more arguments**: - Format string (mandatory) - Optionally, a list of variables whose values should be printed, replacing the format specifiers (e.g. `%d`) in the format string .leftcol[ ```c int int_var = -1; unsigned int uint_var = 12; long int lint_var = 10; float float_var = 2.5; double double_var = 2.5; char char_var = 'a'; char string_var[] = "hello"; // ``` ] .rightcol[ ```c printf("Integer: %d\n", int_var); printf("Unsigned integer: %u\n", uint_var); printf("Long integer: %ld\n", lint_var); printf("Float: %f\n", float_var); printf("Double: %lf\n", double_var); printf("Characters: %c\n", char_var); printf("String: %s\n", string_var); printf("Several variables: %d, %lf, %s\n", int_var, double_var, string_var); // ``` .codelink[
`04-c-variables-types-printf/printf.c`
] ] - See [here](https://linux.die.net/man/3/printf) for a list of all format specifiers/modifiers ??? - It takes one or more arguments. - The first argument is the format string, containing the text to print as well as optional format specifiers that will be replaced with the variables' values. - The following arguments are optional: they are the variables whose values are to be printed, 1 variable per argument. - The format specifier to use depends on the corresponding variable's type. - You can see a few examples on the slide. - percentage d is used for signed integers, percentage u for unsigned ones. - The l length modifier indicates long, for example percentage ld for a signed long int. - We use percentage f for floats and percentage lf for doubles (with printf, percentage f also works for doubles). - Finally, notice the declaration of a string as a character array, with square brackets after the variable name, initialised with a string literal in double quotes. - We can print it with percentage s. --- # Printing to the Console (2) - Make sure to use the right format specifier! - A mismatch is **undefined behaviour**: the compiler only warns with `-Wall`, the program still compiles, and incorrect values are displayed at runtime ```c int my_variable = -42; printf("-42 printed with %%d: %d\n", my_variable); printf("-42 printed with %%u: %u\n", my_variable); // -42 interpreted as an unsigned integer unsigned long long int ull = 5467513055454315; printf("5467513055454315 printed with %%llu: %llu\n", ull); printf("5467513055454315 printed with %%u: %u\n", ull);// interprets only 4 bytes vs. 8 for llu printf("5467513055454315 printed with %%d: %d\n", ull);// low-order 4 bytes, as signed // ``` .codelink[
`04-c-variables-types-printf/printf-bugs.c`
] --- # Summary - Variables - Types - `printf` ---- .center[Feedback form: https://bit.ly/2VslNaB]
??? - So let's recap. - We have seen how to declare and use variables. - Variables can be of different types, which define the size of their storage location in memory: something important to keep in mind. - Finally, we saw how printf can be used to print to the standard output. - In the next video, we will talk about arrays, strings, and the program's command-line arguments. --- class: center, middle # A Few Words about the Development Environment for the Lab Exercise --- name: env # Lab Development Environment --- template: env
--- template: env
--- template: env
--- template: env
--- template: env
--- template: env