# 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.

### 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

```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
