# C 筆記 ## 標頭檔 - 提供一些已經定義好的函式 - 用 #include 來引入標頭檔 - .h 是C標頭檔的副檔名 #### 範例 ```c= #include <stdio.h> // 提供一些函式,例如:printf()、scanf() ``` Actually, it is legal to compile code without including any header ```c= int main() { int a = 0, b = 1; int sum; sum = a + b; } // 在這個例子裡,使用 scanf() 或 printf() 是不合法的 // 因為我們沒有引入 <stdio.h>. ``` ## 簡易程式碼架構 ```c= #include <stdio.h> // 引入標頭檔 // 主函式:編譯器會從這個函式開始執行程式碼 int main() { // 宣告 int a, b, sum; // 輸入 scanf("%d %d", &a, &b); // 運算 sum = a + b; // 輸出 printf("%d\n", sum); // 回傳 return 0; } ``` ## 變數 - 用來儲存數值的東西 - ***命名要有意義*** - ***不同型別的資料其實都是數字,只是大小不同而已*** - 1 byte = 8 bits - 以下是C自帶的基本資料型別 ### int - 名稱:整數 - 大小:4 bytes - 格式字符:%d ### long long - 名稱:長整數 - 大小:8 bytes - 格式字符:%lld ### char - 名稱:字元 - 大小:1 bytes - 格式字符:%c - ASCII編碼: [ASCII - 維基百科,自由的百科全書](https://zh.wikipedia.org/zh-tw/ASCII) ### float - 名稱:浮點數 - 大小:4 bytes - 格式字符:%f ### double - 名稱:長浮點數 - 大小:8 bytes - 格式字符:%lf ### usigned - 名稱:非負整數 - 大小:4 bytes - 格式字符:%u ### pointer - 名稱:指標 - 大小:4 bytes - 格式字符:%p ### 範例 ```c= #include <stdio.h> int main() { int a = 1; long long b = 2; char c = 'A'; float d = 2.3; double e = 4.5; unsigned f = -1; printf("%d, %lld, %c, %f, %lf, %u\n", a, b, c, d, e, f); } // output: 1, 2, A, 2.300000, 4.500000, 4294967295 ``` ### 全域變數 / 區域變數 - 全域變數:宣告在函式與迴圈之外的變數,可以被所有的函式或迴圈使用 - 區域變數:宣告在函式或迴圈之內的變數,只能被特定的函式或迴圈使用 ```c= #include <stdio.h> int globalVariable; int main() { int localVariable; } ``` --- ### 參考 [Data Types in C](https://www.geeksforgeeks.org/data-types-in-c/?ref=lbp) ## 格式字串 ### 簡介 格式字串是一種含有格式字符的特殊字串,可以想像成一個輸入或輸出的模板。例如: ```c= #include <stdio.h> int main() { char h[6] = "hello"; char w[6] = "world"; printf("h is %s.\n", h); printf("w is %s.\n", w); } // output: h is hello. // w is world. ``` ### 格式字符 用來告訴電腦該如何看待後面的數字。例如: ```c= #include <stdio.h> int main() { int a = 48; printf("As an integer, a is %d.\n", a); printf("As a character, a is %c.\n", a); printf("%c + %d = %d\n", a, a, a); } // output: As an integer, a is 48. // As a character, a is 0. // 0 + 48 = 48 // 根據ASCII編碼表,字元'0'是48 ``` #### 基本的格式字符 | int | char | string | float | long long | double | usigned | |:---:|:----:|:------:|:-----:|:---------:|:------:|:-------:| | %d | %c | %s | %f | %lld | %lf | %u | --- ### 參考 [printf() 格式字串的使用方法](https://dev.to/codemee/printf-ge-shi-zi-chuan-de-shi-yong-fang-fa-n8f) ## 輸出 ### printf() 小知識:為什麼是printf()而不是printl()或其他字母呢?因為f代表的是format的意思,即格式化輸出。 ```c= printf(format string, variable1, variable2, ...); ``` #### 範例 ```c= #include <stdio.h> int main() { printf("Zero is %d.\nOne is %d.\n", 0, 1); } // output: Zero is 0. // One is 1. ``` ### putchar() 用來印出字元的函式 ```c= #include <stdio.h> int main() { putchar('a'); putchar(' '); putchar(48); } // output: a 0 // 根據ASCII編碼表,字元'0'是48 ``` ## Input ### scanf() 用法跟printf()很像,但scanf()是用來輸入的 ```c= scanf(format string, address of variable1, address of variable2, ...); ``` #### Example ```c= #include <stdio.h> int main() { int a, b; scanf("%d %d", &a, &b); // & 是取址符號,即取得該變數儲存之位址 printf("%d %d\n", a, b); } // input: 12 13 // output: 12 13 ``` ### getchar() 跟 scanf("%c") 的功能一模一樣 ```c= #include <stdio.h> int main() { char c = getchar(); putchar(c); } // input: ABC // output: A ``` ### gets() / fgets() 如果想要輸入含有空白的字串,可以使用這兩個函式。 --- ### 參考 [fgets函數及其用法,C語言fgets函數詳解](https://tw511.com/a/01/1045.html) ## 運算子 ### 數學運算子 #### + : 加 ```c= #include <stdio.h> int main() { int a = 20, b = 3; printf("%d\n", a + b); } // output: 23 ``` #### - : 減 ```c= #include <stdio.h> int main() { int a = 20, b = 3; printf("%d\n", a - b); } // output: 17 ``` #### * : 乘 ```c= #include <stdio.h> int main() { int a = 20, b = 3; printf("%d\n", a * b); } // output: 60 ``` #### / : 除 ```c= #include <stdio.h> int main() { int a = 20, b = 3; printf("%d\n", a / b); } // output: 6 ``` #### % : 取餘數 ```c= #include <stdio.h> int main() { int a = 20, b = 3; printf("%d\n", a % b); } // output: 2 ``` ### 比較運算子 #### == : 等於 ```c= #include <stdio.h> int main() { int a = 10, b = 20, c = 20; printf("(%d, %d)\n", a == b, b == c); } // output: (0, 1) ``` #### != : 不等於 ```c= #include <stdio.h> int main() { int a = 10, b = 20, c = 20; printf("(%d, %d)\n", a != b, b != c); } // output: (1, 0) ``` #### < : 小於 ```c= #include <stdio.h> int main() { int a = 10, b = 20, c = 20; printf("(%d, %d)\n", a < b, b < c); } // output: (1, 0) ``` #### > : 大於 ```c= #include <stdio.h> int main() { int a = 10, b = 20, c = 20; printf("(%d, %d)\n", a > b, b > c); } // output: (0, 0) ``` #### <= : 小於等於 ```c= #include <stdio.h> int main() { int a = 10, b = 20, c = 20; printf("(%d, %d)\n", a <= b, b <= c); } // output: (1, 1) ``` #### >= : 大於等於 ```c= #include <stdio.h> int main() { int a = 10, b = 20, c = 20; printf("(%d, %d)\n", a >= b, b >= c); } // output: (0, 1) ``` ### 二元運算子 將所有數字以二進位看待來運算 #### & : AND ##### 真值表 | AND | 1 | 0 | |:-----:|:---:|:---:| | **1** | 1 | 0 | | **0** | 0 | 0 | ```c= #include <stdio.h> int main() { int a = 0, b = 1, c = 3; printf("(%d, %d)\n", a & b, b & c); } // output: (0, 1) // 在二進制中,a 是 00000000,b 是 00000001,c 是 00000011 // 在二進制中,0 是 00000000,1 是 00000001 ``` #### | : OR ##### 真值表 | OR | 1 | 0 | |:-----:|:---:|:---:| | **1** | 1 | 1 | | **0** | 1 | 0 | ```c= #include <stdio.h> int main() { int a = 0, b = 1, c = 3; printf("(%d, %d)\n", a | b, b | c); } // output: (1, 3) // 在二進制中,a 是 00000000,b 是 00000001,c 是 00000011 // 在二進制中,1 是 00000001,3 是 00000011 ``` #### ^ : XOR ##### 真值表 | XOR | 1 | 0 | |:-----:|:---:|:---:| | **1** | 0 | 1 | | **0** | 1 | 0 | ```c= #include <stdio.h> int main() { int a = 0, b = 1, c = 3; printf("(%d, %d)\n", a ^ b, b ^ c); } // output: (1, 2) // 在二進制中,a 是 00000000,b 是 00000001,c 是 00000011 // 在二進制中,1 是 00000001,2 是 00000010 ``` #### ~ : 取1的補數 (0、1互換) Ex: 101101 -> 010010 ```c= #include <stdio.h> int main() { int a = 1, b = 2; printf("(%d, %d)\n", ~a, ~b); } // output: (-2, -3) // 在二進制中, a 是 00000001, b 是 00000010 // 在二進制中,-2 是 11111110,-3 是 11111101 ``` #### << : 左移 ```c= #include <stdio.h> int main() { int a = 3; printf("%d\n", a << 2); } // output: 12 // 在二進制中, a 是 00000011 // 在二進制中,12 是 00001100 ``` #### >> : 右移 ```c= #include <stdio.h> int main() { int a = 12; printf("%d\n", a >> 2); } // output: 3 // 在二進制中,a 是 00001100 // 在二進制中,3 是 00000011 ``` ### Assign #### = : 賦值 ```c= #include <stdio.h> int main() { int a; printf("%d\n", a = 2); } // output: 2 ``` #### += : 加並賦值 ```c= a += 1 is equal to a = a + 1 ``` ```c= #include <stdio.h> int main() { int a = 0, b = 0; a + 1; b += 1; printf("(%d, %d)\n", a, b); } // output: (0, 1) ``` #### 我們也可以使用 -=, *=, /=, &=, |=... 如同上面 ### 邏輯運算子 0 是 false ,其他數字是 true true 的預設值是 1 , false 的預設值是 0 #### && : logic AND ##### 真值表 | AND | true | false | |:---------:|:-----:|:-----:| | **true** | true | false | | **false** | false | false | ```c= #include <stdio.h> int main() { int a = 0, b = 3; printf("%d\n", a && b); } // output: 0 ``` #### || : logic OR ##### 真值表 | OR | true | false | |:---------:|:----:|:-----:| | **true** | true | true | | **false** | true | false | ```c= #include <stdio.h> int main() { int a = 0, b = 3; printf("%d\n", a || b); } // output: 1 ``` #### ! : logic NOT ```c= #include <stdio.h> int main() { int a = 0, b = 3; printf("(%d, %d)\n", !a, !b); } // output: (1, 0) ``` ### ++ / -- -- #### Intro 與 += 1 / -= 1 相同,但是放在變數前後用法會有差別 **放在變數後** 先執行該行再 ++ / -- -- ```c= #include <stdio.h> int main() { int a = 0; while (a < 5) printf("%d ", a++); printf("\n"); } // output: 0 1 2 3 4 ``` **放在變數前** 先 ++ / -- -- 再執行該行 ```c= #include <stdio.h> int main() { int a = 0; while (a < 5) printf("%d ", ++a); printf("\n"); } // output: 1 2 3 4 5 ``` ## if / else ### 簡介 我們可以用 if / else 去控制在特定情況下想做的事 ```c= if (條件1) { 條件1成立要做的事 } else if (條件2) { 條件1不成立且條件2成立要做的事 } . . . else { 所有條件都不成立要做的事 } ``` ### 範例 ```c= #include <stdio.h> int main() { int a = 4; if (a > 4) { printf("a > 4\n"); } else if (a < 4) { printf("a < 4\n"); } else { printf("a == 4\n"); } } // output: a == 4 ``` 如果在 if / else 後面只有一行程式碼,那可以省略大括號 ```c= #include <stdio.h> int main() { int a = 4; if (a > 4) printf("a > 4\n"); else if (a < 4) printf("a < 4\n"); else printf("a == 4\n"); } // output: a == 4 ``` ## switch ### 簡介 跟 if / else很像,但效率比較高 ***要記得加"break"*** ```c= switch(參數) { case 常數1: 要做的事 break; case 常數2: 要做的事 break; . . . default: TODO break; } ``` ### 範例 ```c= #include <stdio.h> int main() { int a = 4; switch(a) { case 2: printf("two\n"); break; case 4: printf("four\n"); break; default: printf("default\n"); } } // output: four ``` 如果我們沒打 "break",會變成下面這種情況: ```c= #include <stdio.h> int main() { int a = 4; switch(a) { case 2: printf("two\n"); case 4: printf("four\n"); default: printf("default\n"); } } // output: four // default ``` ## ? : 表達式 ### 簡介 ```c= 條件 ? 條件成立要做的事 : 條件不成立要做的事; ``` ### 範例 ```c= #include <stdio.h> int main() { int a = 1, b = 0; printf("%d\n", a + b ? a : b); } // output: 1 ``` ## 迴圈 ### 簡介 我們可以使用迴圈來執行重複的動作以精簡程式碼 ### while 迴圈 如果目前的狀態符合設定的執行條件,則迴圈會一直重複執行 ```c= while (執行條件) { 要重複做的事 } ``` #### 範例 ```c= #include <stdio.h> int main() { int i = 0; while (i < 5) { printf("%d ", i); i++; } } // output: 0 1 2 3 4 ``` ### for 迴圈 跟while迴圈很像,不過多出了初始值以及迴圈結束後要自動做的事情 ```c= for (初始值; 執行條件; 迴圈結束要做的事情) { 要重複做的事情 } ``` #### 範例 ```c= #include <stdio.h> int main() { for (int i = 0; i < 5; i++) { printf("%d ", i); } } // output: 0 1 2 3 4 ``` 如果迴圈內要做的事情只有一行,那麼可以省略大括號{ } ```c= #include <stdio.h> int main() { for (int i = 0; i < 5; i++) printf("%d ", i); } // output: 0 1 2 3 4 ``` ### break 立刻跳脫迴圈 ```c= #include <stdio.h> int main() { for (int i = 0; i < 5; i++) { if (i == 3) break; printf("%d\n", i); } } // output: 0 // 1 // 2 ``` ### continue 立刻進入下一層迴圈 ```c= #include <stdio.h> int main() { for (int i = 0; i < 5; i++) { if (i == 3) continue; printf("%d\n", i); } } // output: 0 // 1 // 2 // 3 ``` ### 雙重迴圈 ## Array 一個可以儲存多個相同型別變數的容器 ### 宣告 - 編號從0開始 ```c= 變數型別 陣列名稱[長度] = {元素0, 元素1, ...}; ``` #### 範例 ```c= int int_arr[10] = {0}; char str[10] = {'\0'}; void* ptr[10] = {NULL}; // and so on... ``` ### 初始化 - 如果將陣列宣告成全域變數,那麼陣列所有的值會自動被預設成0。 - 如果宣告成區域變數,則會是隨機數值。 - 如果我們只初始化陣列中的部分元素,則剩下的會被預設成0。 #### 範例 ```c= #include <stdio.h> int global_arr[5]; int main() { int local_arr_init[5] = {1, 2, 3}; int local_arr_Noinit[5]; for (int i = 0; i < 5; i++) printf("%d ", global_arr[i]); printf("\n"); for (int i = 0; i < 5; i++) printf("%d ", local_arr_init[i]); printf("\n"); for (int i = 0; i < 5; i++) printf("%d ", local_arr_Noinit[i]); printf("\n"); } // output: 0 0 0 0 0 // 1 2 3 0 0 // random value... ``` ### 獲取特定的元素 - 利用中括號跟編號 [ 編號 ] 去獲取特定元素 - 編號從0開始 ```c= 陣列名稱[編號] ``` #### 範例 ```c= #include <stdio.h> int main() { int arr[3] = {0, 1, 2}; for (int i = 0; i < 3; i++) { printf("%d ", arr[i]); } } // output: 0 1 2 ``` ### 費氏數列 費氏數列定義: $a_n = a_{n-1} + a_{n-2}$ ; $a_{1} = a_{2} = 1$ #### 範例 ```c= #include <stdio.h> int main() { // 宣告 int arr[10]; // 給定費氏數列頭兩項的值 arr[0] = arr[1] = 1; // 計算剩下項的數值 for (int i = 2; i < 10; i++) { arr[i] = arr[i - 1] + arr[i - 2]; } // 輸出 for (int i = 0; i < 10; i++) { printf("%d", arr[i]); printf(i == 9 ? "\n" : " "); } } // output: 1 1 2 3 5 8 13 21 34 55 ``` ### 二維陣列 - 搭配雙重迴圈使用 ```c= type name[row_len][col_len] = { {Element00, Element01, ...}, {Element10, ...}, ... }; ``` | | Column 0 | Column 1 | | -------- | -------- | -------- | | **Row 0**| arr[0][0]| arr[0][1]| | **Row 1**| arr[1][0]| arr[1][1]| #### 範例 ```c= #include <stdio.h> int main() { int arr[5][5]; for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { arr[i][j] = i * 10 + j; } } for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { printf("%02d", arr[i][j]); printf(j == 4 ? "\n" : " "); } } } // ij ij ij ij ij // -------------- // output: 00 01 02 03 04 // 10 11 12 13 14 // 20 21 22 23 24 // 30 31 32 33 34 // 40 41 42 43 44 ``` ## Function Actually we have learned it before in the beginning. ```c= #include <stdio.h> // declare the function called "main" int main() { printf("hello world!\n"); // call the function called "printf()" } // output: hello world! ``` ### Declaration Note that we can also pass no parameter into function like what we do to main function. ```c= return_type function_name(parameter1, parameter2, ...) { TODO return; // depend on your return_type } ``` ### Call Function ```c= function_name(parameter1, parameter2, ...); ``` #### Example ```c= #include <stdio.h> // times 10 int MulBy10(int para) { return para * 10; } int main() { int a = 2; a = MulBy10(a); printf("%d\n", a); } // output: 20 ``` ### Declaration Order Problem... #### An Error Example ```c= #include <stdio.h> // count doesn't know who are add and minus. // This causes an error. int count(int op, int a, int b) { if (op == 1) return add(a, b); else return minus(a, b); } int add(int a, int b) { return a + b; } int minus(int a, int b) { return a - b; } int main() { int op, a, b; scanf("%d %d %d", &op, &a, &b); printf("%d\n", count(op, a, b)); } ``` ***Recommend that declare the function first and then write the implement below*** #### Solution ```c= #include <stdio.h> // Declare functions first. int count(int op, int a, int b); int add(int a, int b); int minus(int a, int b); int main() { int op, a, b; scanf("%d %d %d", &op, &a, &b); printf("%d\n", count(op, a, b)); } // Write functions' implement below int count(int op, int a, int b) { if (op == 1) return add(a, b); else return minus(a, b); } int add(int a, int b) { return a + b; } int minus(int a, int b) { return a - b; } ``` ### Pass Value? Pass Address? Let's look at the example below ```c= #include <stdio.h> void add(int a, int b); int main() { int x = 2, y = 3; add(x, y); printf("x = %d\n", x); } void add(int a, int b) { a += b; printf("a = %d\n", a); } // output: a = 5 // x = 2 ``` You may wonder why x's value doesn't change after running add function. For this example, we only pass the values of x and y to the add function. The compiler copies the value of x to a and the value of y to b, and then assign a + b to a. For this example, we can regard it as below: ```c= #include <stdio.h> int main() { int x = 2, y = 3; int a = x, b = y; a += b; printf("a = %d\n", a); printf("x = %d\n", x); } // output: a = 5 // x = 2 ``` So how do we deal with this problem? Here are two ways to solve it. - **Solution 1:** Use global variables (Recommend if you don't know pointer) ```c= #include <stdio.h> int x = 2, y = 3; void add(); int main() { add(); printf("x = %d\n", x); } void add() { x += y; printf("x = %d\n", x); } // output: x = 5 // x = 5 ``` - **Solution 2:** Use pointer ```c= #include <stdio.h> void add(int* a, int* b); int main() { int x = 2, y = 3; add(&x, &y); // use & can get the variable's address printf("x = %d\n", x); } void add(int* a, int* b) { *a += *b; // use * can get the pointer's value printf("a = %d\n", *a); } // output: a = 5 // x = 5 ``` ## Recursion ### Intro A function calls itself again and again. ![](https://hackmd.io/_uploads/rJjn8jzdn.png) ### Example ```c= #include <stdio.h> void func_f(int a) { if (a > 0) func_f(a - 1); printf("%d ", a); } int main() { func_f(5); } // output: 0 1 2 3 4 5 ``` ### Count factorial Note that $n! = n(n-1)(n-2)... 2*1$ ```c= #include <stdio.h> int countFactorial(int a) { if (a <= 1) return 1; // stop condition return a * countFactorial(a - 1); // call itself recursively } int main() { printf("%d\n", countFactorial(5)); } // output: 120 // Note that 5 * 4 * 3 * 2 * 1 == 120 ``` ### Fibonacci sequence Note that Fibonacci sequence: $a_n = a_{n-1} + a_{n-2}$ ; $a_{1} = a_{2} = 1$ ```c= #include <stdio.h> int rec(int a, int b, int k); int main() { int k = 10; printf("arr[%d] = %d\n", k, rec(0, 1, k)); } int rec(int a, int b, int k) { if (k == 1) return b; // stop condition return rec(b, a + b, k - 1); // call itself recursively } // output: arr[10] = 55 ``` ### Prefix Calculator What is prefix calculator? If we put operator to the front, and we call it prefix expression For example: (1 + 2) * 4 => * + 1 2 4 ![](https://hackmd.io/_uploads/Skpu9EQuh.png) ```c= #include <stdio.h> int count() { char c; scanf("%c", &c); if (c == '+') return count() + count(); if (c == '-') return count() - count(); if (c == '*') return count() * count(); if (c == '/') return count() / count(); return c - '0'; } int main() { printf("%d\n", count()); } // input: *+124 // output: 12 ``` ### Minimum Step Given a maze with '#', '.', 'S', 'E'. '#': wall '.': path 'S': start point 'E': end point Please count the minimum steps to reach the end point from the start point. **Input** First row will have two integer H, W, which means the height and the width of the map repectively. And then there will be H rows, W columns characters with only '#', '.', 'S', 'E'. It guarantees that the maze will be surrounded by '#'. 5 <= H, W <= 100000 **Output** Please output the minimum steps from 'S' to 'E'. Please output '\n' in the end. **Sample Input** ```= 6 7 ####### ##S...# #...#.# #.##E.# #.....# ####### ``` **Sample Output** ```= 6 ``` <!--**Sample Code** ```c= #include <stdio.h> #include <limits.h> int R, C, Start[2], min_distance = INT_MAX; char map[10001][10001]; // 1 <= R, C <= 10000 void walk(int row, int col, int distance); int main() { // get the range of map scanf("%d %d", &R, &C); // get the map and the index of start for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { scanf(" %c", &map[i][j]); if (map[i][j] == 'S') { Start[0] = i; Start[1] = j; } } } // recursion walk(Start[0], Start[1], 0); // output printf("%d\n", min_distance == INT_MAX ? 0 : min_distance); } void walk(int row, int col, int distance) { // more than the result we count before if (distance > min_distance) return; // reach the end point if (map[row][col] == 'E') { min_distance = distance; return; } // try four directions for (int i = -1; i <= 1; i += 2) { for (int j = 0; j <= 1; j++) { if (map[row + i * j][col + i * (1 - j)] != '#') { map[row][col] = '#'; walk(row + i * j, col + i * (1 - j), distance + 1); map[row][col] = '*'; } } } } ```--> ## Pointer A type of variables that store variable's ```c= #include <stdio.h> int main() { int a = 5; int* ptr = &a; printf("The value of a is %d.\n", a); printf("The address of a is %p\n", &a); printf("The value of ptr is %p\n", ptr); printf("The value store in %p is %d\n", ptr, *ptr); printf("The address of ptr is %p\n", &ptr); } // output: The value of a is 5. // The address of a is 0061FF1C // The value of ptr is 0061FF1C // The value store in 0061FF1C is 5 // The address of ptr is 0061FF18 ``` ## struct ### Intro We can use struct to define our own data types ```c= struct structure_name { // data }; ``` ### Example ```c= #include <stdio.h> struct _student { int number; int age; int height; }; int main() { struct _student s; // declaration s.number = 1; // use '.' to access specific data in the structure you defined s.age = 13; s.height = 176; printf("Number %d is %d years old and %d centimeters tall.\n", s.number, s.age, s.height); } // output: Number 1 is 13 years old and 176 centimeters tall. ``` ## typedef ### Intro Assign a name for a specific data type. ```c= typedef data_type_name your_own_name; ``` ### Example ```c= #include <stdio.h> typedef int Integer; typedef struct _node { int value; struct _node* next; } Node; int main() { Integer a = 5; Node n; n.value = 5; n.next = NULL; printf("%d, %d\n", a, n.value); } // output: 5, 5 ``` ## sizeof() ### Intro Get how many bytes a variable or a data type is ```c= sizeof(data_type); sizeof(variable_name); ``` ### Example ```c= #include <stdio.h> int main() { int a, arr[5]; printf("%d, %d, %d\n", sizeof(a), sizeof(arr), sizeof(int)); } // output: 4, 20, 4 ``` ## malloc() ### Intro Allocate memories with given size and return the head address back ```c= malloc(how_many_bytes_of_memories_you_want_to_allocate); ``` ### Example ```c= #include <stdio.h> #include <stdlib.h> int main() { int* ptr = (int*) malloc(sizeof(int)); *ptr = 20; printf("%d\n", *ptr); } // output: 20 ``` ## Linked List ![](https://hackmd.io/_uploads/S1uN2LTj2.jpg)