結構
把幾個值綁成一個東西。 · ⏱ 約 30 分鐘
你會學到三件事
struct 把幾個變數包成一個
- C 宣告時一定要寫
struct 這個字
. 和 -> 的差別,以及為什麼有兩個
開始之前
一個點有 x 和 y。用兩個變數的話,它們只是碰巧放在一起——
函式要傳兩個、陣列要開兩個、改一個忘了另一個。
struct 讓它們變成一個東西。
🟢 先把編輯器打開,跟著下面一起做:跟著做
一、定義一個型別
把幾個值綁成一個型別:
1struct Point {2 int x;3 int y;4};
⚠️ 最後那個分號不能少。 這是 C 少數幾個「大括號後面要分號」的地方,
而漏掉它的錯誤訊息通常指向下一行——很難查。
這一段不會產生任何變數。它在說「以後有一種東西叫 Point,長這樣」。
二、🔴 用的時候要寫 struct
積木盤上這一顆寫著「定義結構 …」;
而底下設定欄位的那幾行是「把 … 設成 …」(第 5 課用過)。
C 裡用它的時候,前面那個 struct 不能省:
⚠️ C 一定要寫那個 struct,而 C++ 可以省略成 Point p;。
這是 C 和 C++ 一個很表面、而每天都會遇到的差別。
(老程式碼常見 typedef struct { ... } Point; 就是為了省掉它。)
三、. 取成員
拿裡面的值用一個點:
1p.x = 3;2p.y = 4;3printf("%d %d\n", p.x, p.y);
和 C++ 完全一樣。
四、-> 是「透過指標取成員」
手上是指標的時候,用箭頭:
1struct Point *q = &p;2printf("%d\n", q->x);
q 是一個指標,所以不能直接 q.x——要先去那個地址。
(*q).x // 先去 q 指的地方,再取 x
q->x // 一模一樣,只是好寫好讀
⚠️ -> 就是 (*). 的縮寫,沒有別的意思。
判準很簡單:
| 左邊是什麼 |
用哪個 |
| 一個結構 |
. |
| 一個指向結構的指標 |
-> |
⚠️ 用錯的話編譯器會攔你,所以這個錯不可怕——它只是煩。
五、為什麼結構常常用指標傳
傳指標就不會複製一整份:
1void move(struct Point *p) {2 p->x = p->x + 1;3}
兩個理由:
- 要改到本體(第 3 課那件事)
- 不用複製一整個結構——結構大的時候,傳值等於整份拷貝
所以 C 的慣例是:結構參數幾乎都傳指標。
完成的樣子
這一課的參考做法——程式碼每一行的號碼,就印在對應的那塊積木上。
1#include <cstdio>2using namespace std;3struct Point {4 int x;5 int y;6};7 8int main() {9 struct Point p;10 p.x = 3;11 p.y = 4;12 printf("%d %d\n", p.x, p.y);13 struct Point *q = &p;14 printf("%d\n", q->x);15 return 0;16}
換你了
加一個 struct Point 的陣列(三個點),用迴圈填值再印出來。
再進階:寫一個函式算兩點的距離——參數用指標傳。
到編輯器做這一題:練習:三個點的陣列,用迴圈填值再印出來
做一個
struct Student 裡有 math 和 eng。開一個三人的陣列,填上分數,
找出總分最高的那個人,印出他的編號和平均。
資料用這三筆:80 90、95 95、60 100。
🔴 沒有 struct 的話,這一題要開兩個平行陣列 math[3] 和 eng[3]——
而那兩個陣列沒有任何東西保證它們的第 i 格講的是同一個人。
到編輯器做這一題:做一個:總分最高的那一個
這一課你做了什麼
- 你定義了一個自己的型別
- 你知道 C 宣告時要寫
struct,而 C++ 不用
- 你分得出什麼時候用
.、什麼時候用 ->
如果卡住了
| 你看到 |
多半是因為 |
| 錯誤訊息指著結構定義的下一行 |
定義結尾的分號漏了 |
Point p; 說找不到型別 |
C 要寫 struct Point p; |
q.x 編譯錯誤 |
q 是指標,要用 q->x |
| 函式裡改了值外面沒變 |
參數傳的是複本。要傳指標 |
在編輯器打開這一課 →