<!-- .slide: data-transition="convex-in convex-out" -->
# Function
###### tags: `lion_1081`
---
<!-- .slide: data-transition="convex-in convex-out" -->
# Introduce
1. Scope
2. Lifetime
3. Variable
----
<!-- .slide: data-transition="convex-in convex-out" -->
# Scope
#### 一個變數能觸及到的範圍
----
# Lifetime
#### 一個變數生存的時間
#### 當變數的lifetime過了,則這個變數就完全無效了
----
<!-- .slide: data-transition="convex-in convex-out" -->
# Variable
#### 1. 全域變數(Global variable)
#### 2. 區域變數(Local variable)
#### 3. 區塊變數(Block variable)
----
<!-- .slide: data-transition="convex-in convex-out" -->
## 全域變數 Global variable
```c=
#include<stdio.h>
int A = 1; //Global variable
int main(void){
// statment
return 0;
}
```
- 在整個程式之中都能看到它的存在,且可以呼叫使用
- Lifetime 始於程式開始,終止於程式結束
- 初學者不建議使用,除非必要
----
<!-- .slide: data-transition="convex-in convex-out" -->
## 區域變數 Local variable
```c=
#include<stdio.h>
int main(void){
int B = 10; //Local variable
printf("B = %d\n", B);
return 0;
}
```
- 只能在該函式內使用,其他函式不可使用該變數
- Lifetime 始於函式被呼叫後,止於函式執行完畢
----
<!-- .slide: data-transition="convex-in convex-out" -->
## 區塊變數 Block variable
```c=
#include<stdio.h>
int main(void){
int i; // Local variable
for( i = 0; i < 5; ++i) {
int B = 0; //Block variable
++B;
printf("B = %d\n", B);
}
return 0;
}
```
- 只有該區塊內可使用
- Lifetime 始於該區塊開始之時,終止於該區塊結束
- hint: -std=c99
----
<!-- .slide: data-transition="convex-in convex-out" -->
```c=
#include<stdio.h>
int A = 1; //Global variable
int main(void){
int B = 10; //Local variable
for(B = 0; B < 5; ++B) {
int C = 0; //Block variable
++C;
printf("C = %d\n", C);
}
printf("A = %d\n", A);
printf("B = %d\n", B);
return 0;
}
```
---
<!-- .slide: data-transition="convex-in convex-out" -->
# So, what is function?
----
<!-- .slide: data-transition="convex-in convex-out" -->
# 一個簡單的範例
## A+B=C, print C
----
<!-- .slide: data-transition="convex-in convex-out" -->
## 在學習function之前,你可能會寫成這樣
```c=
#include<stdio.h>
int main(){
int a, b, c;
scanf("%d%d", &a, &b);
c = a + b;
printf("%d\n", c);
}
```
#### or
```c=
#include<stdio.h>
int main(){
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", a + b);
}
```
----
<!-- .slide: data-transition="convex-in convex-out" -->
## 寫成function就像
```clike=
int add(int A, int B){
int C;
C = A + B;
return C;
}
```
----
<!-- .slide: data-transition="convex-in convex-out" -->
# 那寫成一個可執行的code 會長怎樣?
----
<!-- .slide: data-transition="convex-in convex-out" -->
```clike=
#include<stdio.h>
int add(int A, int B){
int C;
C = A + B;
return C;
}
int main(){
int a, b, c;
scanf("%d%d", &a, &b);
c = add(a, b);
printf("%d\n", c);
}
```
----
<!-- .slide: data-transition="convex-in convex-out" -->
## Line 2:

----
<!-- .slide: data-transition="convex-in convex-out" -->
## Line 2(cont.):
- 回傳的 type 可以是所有的 type + void
- void 表示說 該function不會回傳任何東西
----
<!-- .slide: data-transition="convex-in convex-out" -->
## Line 3~5:

----
<!-- .slide: data-transition="convex-in convex-out" -->
## Line 3~5(cont.):
- function中的return statement一定要和function的return type一樣
- 這裡的A的type是int,但這裡強制轉為char回傳
```clike=
char func(int A){
return A;
}
int main(){
int a = 97;
printf("%c\n", func(a));
}
```
----
<!-- .slide: data-transition="convex-in convex-out" -->
## Line 10:

----
<!-- .slide: data-transition="convex-in convex-out" -->

----
<!-- .slide: data-transition="convex-in convex-out" -->
## Practice 1:
- Make a main & power function
- main function do the input and output
- power function do x(input 1) to the power of n(input 2), then return to the main function
----
<!-- .slide: data-transition="convex-in convex-out" -->
# [ANS](https://github.com/NightKirie/lion2017/blob/master/function/practice1.c)
----
<!-- .slide: data-transition="convex-in convex-out" -->
## 你也可以寫成這樣
```c=
#include<stdio.h>
int main(){
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", add(a, b));
}
```
----
```c=
#include<stdio.h>
// 從A加總到B
int func(int A,int B){
int i,sum=0;
for(i=A;i<=B;++i){
sum += i;
}
return sum;
}
int main(){
int a, b, c;
a = func(2,8);
b = func(4,12);
c = func(5,13);
printf("%d %d %d\n", a, b, c);
}
```
----
<!-- .slide: data-transition="convex-in convex-out" -->
## Conclusion of Function
|優點|缺點|
|:-|:-|
|1.可讀性提高|1. 使用更多的記憶體空間|
|2. 較容易維護|2. 型別問題|
|3. 可重複使用||
----
```clike=
#include<stdio.h>
int add(int A, int B){ // A,B are parameters
int C;
C = A + B;
return C;
}
int main(){
int a, b, c;
scanf("%d%d", &a, &b);
c = add(a, b); // a,b are arguments
printf("%d\n", c);
}
```
<!-- .slide: data-transition="convex-in convex-out" -->
- parameter 和 argument 可以使用相同的名字 (在 call by value 的時候,仍為不同的東西)
- 我們通常會把<font color="cyan"> parameter</font> 叫做<font color="cyan"> "formal parameter" </font>,把 <font color="lime">argument</font> 叫做 <font color="lime">actual parameter"</font>
----
- Actual parameter 可以是一個 <font color="cyan">constant</font> (ex. 4), 一個 <font color="cyan">variable</font> (ex. x), 或甚至是一個 <font color="cyan">expression</font> (ex. x+y)
- 當你在使用任何變數時,請注意一下他是屬於哪種 scope
----
<!-- .slide: data-transition="convex-in convex-out" -->
## Practice 2:
- make a main function to input (a,b,c) of an quadratic equation $ax^2+bx+c$,
- then make a function to calculate the quadratic formula,
- in the end, return the biggest answer to main function to output it
- hint: use <math.h> & sqrt() & gcc -o xxx xxx.c -lm
----
<!-- .slide: data-transition="convex-in convex-out" -->
- Bonus 1: add judgement if it's real number, print the error message if not
- Bonus 2: make this code in loop until input is EOF
----
<!-- .slide: data-transition="convex-in convex-out" -->
# [Ans](https://github.com/NightKirie/lion2017/blob/master/function/practice2.c)
---
<!-- .slide: data-transition="convex-in convex-out" -->
## Call by value & address
----
### Call by value
<!-- .slide: data-transition="convex-in convex-out" -->
```clike=
#include<stdio.h>
void add(int a){
++a;
}
int main(){
int a = 1;
add(a);
printf("%d\n", a);
}
```
- print out 1
----
### call by value
### 就是把 **值** 複製給對方
| 執行前| main的a | add的a| 執行後| main的a | add的a |
| -------- | -------- | --------|-------- | -------- | -------- |
|value|1|1|value|1|2|
|address|0x04|0x16|address|0x04|0x16|
----
<!-- .slide: data-transition="convex-in convex-out" -->
### Call by address
```clike=
#include<stdio.h>
void add(int* a){
++(*a);
}
int main(){
int a = 1;
add(&a);
printf("%d\n", a);
}
```
- print out 2
----
#### &a 表示取得 a 的位址
#### * a 表示取得對應這個位址的值
| 執行前| main的a | add的a| 執行後| main的a | add的a |
| -------- | -------- | --------|-------- | -------- |-------- |
|value|1|0x04|value|2|0x04|
|address|0x04|0x16|address|0x04|0x16|
#### add的\*a 就是 main的a的值
---
## 如何把array傳進function呢 ?
----
- 當傳進一個array時
- argument就是array的名字
- parameter的大小必須要和原本的array一樣
----
<!-- .slide: data-transition="convex-in convex-out" -->
#### 1-D array
```clike=
#include<stdio.h>
//void add_one(int *A)
//void add_one(int A[])
void add_one(int A[5]){
int i;
for(i = 0; i < 5; i++)
printf("%d\n", ++A[i]);
}
int main(){
int a[5] = {0,1,2,3,4};
add_one(a);
}
```
----
<!-- .slide: data-transition="convex-in convex-out" -->
#### 2-D array
```clike=
#include<stdio.h>
//void add_one(int A[][3])
void add_one(int A[2][3]){
int i,j;
for(i = 0; i < 2; i++)
for(j = 0; j < 3; j++)
printf("%d\n", ++A[i][j]);
}
int main(){
int a[2][3] = {{0,1,2},{4,5,6}};
add_one(a);
}
```
----
## Practice 3:
- Make a main & "multi" function
- Inside main function, make a array can store 10 integer, the elements are 1 to 10
- Using the "multi" function to calculate the multiplication of this 10 elements and print it out
----
<!-- .slide: data-transition="convex-in convex-out" -->
# [ANS](https://github.com/NightKirie/lion2017/blob/master/function/practice3.c)
----
<!-- .slide: data-transition="convex-in convex-out" -->
- 當傳進一個n維array A[a][b][c]....[n],
- 在a已知的前提下,parameter必須宣告一個至少像B[][b][c].....[n]的陣列
- 因為電腦會把n維轉成1維,並將它存在1維address中
- Ex. 2-D array int a[3][4]
- => (i x 4 + j) x 4 bytes + a[0][0]'s address = a[i][j]'s address
----
<!-- .slide: data-transition="convex-in convex-out" -->
```clike=
#include<stdio.h>
void add_one(int A[3][4]){
for(int i = 0; i < 3; i++)
for(int j = 0; j < 4; j++)
printf("%d\n%p\n", ++A[i][j], &A[i][j]);
}
int main(){
int a[3][4] = {{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};
add_one(a);
}
```
- A[i][j] 與 A[i][j+1] 兩address之間相差 4 bytes
- A[i][3] 與 A[i+1][0] 兩address之間也相差 4 bytes
----
<!-- .slide: data-transition="convex-in convex-out" -->
## array 是 call by address
<!-- .slide: data-transition="convex-in convex-out" -->
```clike=
#include<stdio.h>
void add_one(int A[3][4]){
for(int i = 0; i < 3; i++)
for(int j = 0; j < 4; j++)
++A[i][j];
}
int main(){
int a[3][4] = {{0,1,2,3}, {4,5,6,7}, {8,9,10,11}};
add_one(a);
for(int i = 0; i < 3; i++)
for(int j = 0; j < 4; j++)
printf("%d\n", a[i][j]);
}
```
print: 1~12
----
<!-- .slide: data-transition="convex-in convex-out" -->
- 當我們在傳一個array的時候,我們實際上是傳進該array第一個element的address
- 也就是說,add_one(a)的a就是array中第一個element的address
```clike=
#include<stdio.h>
//void add_one(int* A)
void add_one(int A[3][4]){
printf("address of A[3][4] is %p\n", &A[0][0]);
printf("address of A is %p\n", A); //in this function, A is a pointer
}
int main(){
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
add_one(a);
printf("address of a is %p\n", a);
printf("address of a[0][0] is %p\n", &a[0][0]);
}
```
- **所以說,array 是一種 pointer**
---
<!-- .slide: data-transition="convex-in convex-out" -->
## Supplements
----
<!-- .slide: data-transition="convex-in convex-out" -->
## Forward declaration
----
<!-- .slide: data-transition="convex-in convex-out" -->
```clike=
#include<stdio.h>
int add(int, int);
int main(){
int a, b, c;
scanf("%d%d", &a, &b);
c = add(a, b);
printf("%d\n", c);
}
int add(int A, int B){
int C;
C = A + B;
return C;
}
```
- 可以把第二行刪掉,看看compile後的訊息
----
<!-- .slide: data-transition="convex-in convex-out" -->
- 那我們如何寫forward declaration?
- 你只需要宣告 function return type, function name, and parameter type
- 建議 : forward declaration的順序跟function的先後順序一樣,從上到下排列
----
<!-- .slide: data-transition="convex-in convex-out" -->
## return & exit
- hint: <stdlib.h>
----
<!-- .slide: data-transition="convex-in convex-out" -->
```clike=
#include<stdio.h>
#include<stdlib.h>
void test();
int main(){
printf("main start\n");
test();
printf("main end\n");
}
void test(){
printf("inside test\n");
return;
//exit(1);
}
```
----
<!-- .slide: data-transition="convex-in convex-out" -->
- 使用exit,程式會在讀到exit的時候結束
- return則是從一個function中返回,並將控制權給使用該function的function
- e.g.從test返回,並把控制權給main
----
- 我們可以在terminal上使用"echo $?"來看上一個執行的指令所回傳的值
- exit(0) 代表程式正常結束
- exit(<非零>)則表示程式異常終止
{"metaMigratedAt":"2023-06-15T00:38:58.495Z","metaMigratedFrom":"Content","title":"Function","breaks":true,"contributors":"[{\"id\":\"8329238d-0a43-44c6-9d21-cb0bdf1001b8\",\"add\":19665,\"del\":8199}]"}