###### tags: `CPP` `Arduino`
# 02 區塊、縮排與自定義函式
在上一篇提到過有左右大括號的那一行不需要用英文的分號結尾, 這種有左右大括號括起來的部分稱為**區塊 (block)**, 區塊內會包含其他的敘述, 一般都會在區塊內的敘述前方加上空格**往右縮排**, 以便容易辨識區塊的結構, 縮不縮排並不影響程式的執行結果, 但卻可以讓程式更容易閱讀:
```cpp=
void setup() {
// put your setup code here, to run once:
pinMode(5, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(5, LOW);
delay(1000);
digitalWrite(5, HIGH);
delay(1000);
}
```
2~3 行的縮排讓我們從視覺上就可以分辨這兩行是一個群組, 而 7~11 又是另一個群組, 你可以和底下不縮排的樣子比較, 有縮排是不是結構清楚多了:
```cpp=
void setup() {
// put your setup code here, to run once:
pinMode(5, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(5, LOW);
delay(1000);
digitalWrite(5, HIGH);
delay(1000);
}
```
許多教材在縮排時都是以 4 個空格為標準, 本系列課程在縮排時則是以 2 個空格為標準, 一方面 2 個空格已經可以適度區隔層級, 另一方面則是可以避免往右縮太多空格讓程式橫向變得過寬, 要左右捲動才能閱讀的麻煩。
## 自行定義函式
你可以發現在閃爍 LED 的程式中有兩個區塊, 這兩個區塊的開頭那一行, 也就是第 1、6 兩行都有一個很像是呼叫函式的寫法, 這是讓我們**自己定義函式**提供**特定功能**的敘述:
1. 左大括號的左邊是函式的名稱, 跟著一對小括號:
```cpp
void setup() {
... // 要執行的敘述寫在這個區塊內
}
void loop() {
... // 要執行的敘述寫在這個區塊內
}
```
2. 最前面的 "void" 表示這個函式**沒有運算結果**, 我們等到後面會再進一步說明。
4. 小括號內是空的, 表示呼叫這個函式時不需要參數。
4. 小括號後要跟著一個**區塊**, 呼叫這個函式時要執行的敘述就寫在區塊內。
5. 一般來說, 定義函式時都會寫成多行, 但要注意的是這種以區塊結尾的敘述**不需要加上英文分號**。
這個程式中定義了兩個函式, 分別是 [`setup`](https://www.arduino.cc/reference/en/language/structure/sketch/setup/) 和 [`loop`](https://www.arduino.cc/reference/en/language/structure/sketch/loop/), 他們和之前介紹過的 `pinMode` 或是 `digitalWrite` 不一樣, 你不會在程式中去呼叫他們, 這是 Arduino 規定每一個程式都一定要定義的函式。每當你上傳程式, 或是按了板子上的 RESET 鈕、重新接上 USB 傳輸線供電時, 就會開始執行已上傳的程式, 它會自動**先呼叫 `setup` 函式一次**, 然後**重複不停地呼叫 `loop` 函式**, 流程如下:
```flow
st=>start: 開始
setup=>subroutine: setup()
loop=>subroutine: loop()
st->setup->loop->loop
loop@>loop({"stroke":"blue"})
```
所以我們通常會把準備工作寫在 `setup` 內, 然後在 `loop` 中再依據感測器的偵測結果變化輸出狀態, 例如偵測到環境變暗時點亮 LED 等等。
也正是因為這樣的流程, 所以閃爍 LED 的程式雖然在 `loop` 中只有亮/熄 LED 一次, 但因為 `loop` 會被重複呼叫, 就會造成**不斷亮/熄的閃爍效果**了。
瞭解 Arduino 程式的基本結構後, 我們就可以進一步瞭解 C++ 的[變數與數學運算](/SCwiZ01ZTgC9kj6JuVu_dA)了。