1. 前言
什麼是 C 語言的箭頭運算子?
C 語言是一種廣泛用於系統程式與嵌入式軟體開發的程式語言。其中的「箭頭運算子(->
)」在操作結構體指標時非常方便。
使用箭頭運算子可以簡潔且具可讀性地存取結構體成員。特別是在透過指標處理資料的情境下,它被頻繁使用,因此理解它的用法十分重要。
本文的讀者對象與學習目標
本文適合以下讀者:
- 正在學習 C 語言,並且已具備結構體與指標基礎知識的人。
- 想更深入了解箭頭運算子的使用方式與應用範例的人。
- 希望提升程式碼可讀性與執行效率的開發者。
本文將從箭頭運算子的基本用法到應用範例,再到注意事項與錯誤排查,進行全面解說。透過學習,讀者將能撰寫出更實用的程式。

2. 箭頭運算子的基礎與用法
箭頭運算子是什麼?符號與語法解析
箭頭運算子(->
)是 C 語言中用來透過指標存取結構體成員的運算子。
語法
pointer->member;
這段語法等同於:
(*pointer).member;
相較於使用括號與星號的寫法,箭頭運算子更簡潔且可讀性更高,因此被廣泛使用。
點運算子(.
)與箭頭運算子的差異
存取結構體成員的方法有兩種:
- 點運算子(
.
)
用於直接操作結構體變數。
struct Person {
char name[20];
int age;
};
struct Person p = {"Alice", 25};
printf("%s
", p.name); // 使用點運算子
- 箭頭運算子(
->
)
用於透過結構體指標操作成員。
struct Person {
char name[20];
int age;
};
struct Person p = {"Alice", 25};
struct Person *ptr = &p;
printf("%s
", ptr->name); // 使用箭頭運算子
差異總結
- 點運算子用於直接存取結構體變數。
- 箭頭運算子用於透過指標存取結構體成員。
箭頭運算子的語法與基本範例
範例1: 使用結構體與指標的基本操作
#include <stdio.h>
#include <string.h>
// 結構體定義
struct Person {
char name[20];
int age;
};
int main() {
// 建立結構體變數與指標
struct Person p1;
struct Person *ptr;
// 指標指向變數位址
ptr = &p1;
// 使用箭頭運算子存取成員
strcpy(ptr->name, "Alice");
ptr->age = 25;
// 輸出
printf("Name: %s
", ptr->name);
printf("Age: %d
", ptr->age);
return 0;
}
執行結果:
Name: Alice
Age: 25
在此範例中,將結構體Person
的變數p1
的位址指定給指標ptr
,並透過箭頭運算子存取結構體成員。

3. 箭頭運算子的應用場景【具體範例】
在鏈結串列中的箭頭運算子應用
鏈結串列是常用的資料結構之一。以下示範如何使用箭頭運算子操作鏈結串列。
範例1: 單向鏈結串列的實作
#include <stdio.h>
#include <stdlib.h>
// 節點定義
struct Node {
int data;
struct Node *next;
};
// 建立新節點的函式
struct Node* createNode(int data) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// 顯示串列內容的函式
void displayList(struct Node *head) {
struct Node *current = head;
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next; // 使用箭頭運算子
}
printf("NULL
");
}
int main() {
// 建立節點
struct Node *head = createNode(10);
head->next = createNode(20); // 使用箭頭運算子連結下一個節點
head->next->next = createNode(30); // 再連結下一個節點
// 顯示串列內容
displayList(head);
return 0;
}
執行結果:
10 -> 20 -> 30 -> NULL
在這個範例中,透過箭頭運算子來操作下一個節點的連結,讓程式能有效率地管理資料。
在樹狀結構中的應用
樹狀結構也是箭頭運算子常用的資料結構之一。以下展示二元搜尋樹的例子。
範例2: 在二元搜尋樹中新增與搜尋節點
#include <stdio.h>
#include <stdlib.h>
// 節點定義
struct TreeNode {
int data;
struct TreeNode *left;
struct TreeNode *right;
};
// 建立新節點的函式
struct TreeNode* createNode(int data) {
struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 新增節點的函式
struct TreeNode* insertNode(struct TreeNode* root, int data) {
if (root == NULL) {
return createNode(data);
}
if (data < root->data) {
root->left = insertNode(root->left, data); // 使用箭頭運算子
} else {
root->right = insertNode(root->right, data); // 使用箭頭運算子
}
return root;
}
// 前序遍歷的函式
void preorderTraversal(struct TreeNode* root) {
if (root != NULL) {
printf("%d ", root->data);
preorderTraversal(root->left); // 遞迴遍歷左子樹
preorderTraversal(root->right); // 遞迴遍歷右子樹
}
}
int main() {
struct TreeNode* root = NULL;
// 新增節點
root = insertNode(root, 50);
insertNode(root, 30);
insertNode(root, 70);
insertNode(root, 20);
insertNode(root, 40);
// 前序遍歷輸出
printf("Preorder Traversal: ");
preorderTraversal(root);
printf("
");
return 0;
}
執行結果:
Preorder Traversal: 50 30 20 40 70
這段程式利用箭頭運算子連結左右子節點並構建二元樹,讓處理指標的程式碼更簡潔。
動態記憶體配置與箭頭運算子結合
箭頭運算子在動態記憶體配置的情境下也經常使用。以下範例展示如何建立結構體並存取資料。
範例3: 使用 malloc 與箭頭運算子
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Student {
char name[20];
int age;
};
int main() {
// 動態配置記憶體
struct Student *s = (struct Student*)malloc(sizeof(struct Student));
// 資料輸入
printf("Enter name: ");
scanf("%s", s->name);
printf("Enter age: ");
scanf("%d", &(s->age));
// 輸出
printf("Name: %s, Age: %d
", s->name, s->age);
// 釋放記憶體
free(s);
return 0;
}
執行結果:
Enter name: Alice
Enter age: 20
Name: Alice, Age: 20
在此範例中,箭頭運算子用來存取動態配置的記憶體中的資料。

4. 理解箭頭運算子的內部運作
箭頭運算子與點運算子的等價性
箭頭運算子(->
)等價於以下寫法:
ptr->member;
(*ptr).member;
這兩種表示方式都能存取指標 ptr
所指向的結構體成員 member
。
具體範例
#include <stdio.h>
#include <string.h>
struct Person {
char name[20];
int age;
};
int main() {
struct Person p = {"Alice", 25};
struct Person *ptr = &p;
// 使用箭頭運算子
printf("%s
", ptr->name);
// 使用點運算子的等價寫法
printf("%s
", (*ptr).name);
return 0;
}
執行結果:
Alice
Alice
由此可見,箭頭運算子其實就是 (*ptr).member
的簡潔語法。在經常操作指標的程式中,能讓程式碼更易讀、更簡單。
作為語法糖的角色
箭頭運算子屬於「語法糖」(Syntax Sugar)。所謂語法糖,是指不影響程式執行結果,但能讓程式碼更簡潔、易懂的語法。
範例:
(*ptr).member; // 標準語法(較冗長)
ptr->member; // 簡潔易讀的語法糖
使用語法糖可以避免括號遺漏等小錯誤,並提升程式的維護性。
記憶體存取與指標機制
使用箭頭運算子時,必須理解指標實際指向記憶體中的哪個位置。
記憶體模型示意:
記憶體位址 | 值 |
---|---|
0x1000 | 結構體起始位置 |
0x1004 | 成員1(name) |
0x1020 | 成員2(age) |
當指標指向 0x1000
時,箭頭運算子會自動處理位移計算,存取對應的成員。
範例4: 考慮記憶體配置的存取
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Data {
int id;
char name[20];
};
int main() {
struct Data *ptr = (struct Data*)malloc(sizeof(struct Data));
ptr->id = 101;
strcpy(ptr->name, "Alice");
printf("ID: %d, Name: %s
", ptr->id, ptr->name);
free(ptr); // 釋放記憶體
return 0;
}
執行結果:
ID: 101, Name: Alice
這段程式展示了如何有效率地進行記憶體配置與資料管理。箭頭運算子在這種情境中特別實用。

5. 使用箭頭運算子時的注意事項與錯誤對策
常見錯誤與避免方法
使用箭頭運算子時,需要特別注意指標與記憶體管理。以下介紹常見錯誤與解決方法。
錯誤1: 參照 NULL 指標
情況: 當指標為 NULL 時使用箭頭運算子,會導致執行期錯誤(Segmentation Fault)。
錯誤範例:
struct Data {
int id;
};
int main() {
struct Data *ptr = NULL;
ptr->id = 10; // 錯誤發生
return 0;
}
解決方法: 使用指標前務必檢查是否為 NULL。
修正版:
struct Data {
int id;
};
int main() {
struct Data *ptr = NULL;
if (ptr != NULL) {
ptr->id = 10;
} else {
printf("指標為 NULL
");
}
return 0;
}
錯誤2: 記憶體配置失敗
情況: 當 malloc
配置失敗時,指標會是 NULL,這時若使用箭頭運算子會出錯。
錯誤範例:
struct Data {
int id;
};
int main() {
struct Data *ptr = (struct Data*)malloc(sizeof(struct Data));
ptr->id = 10; // 若配置失敗會發生錯誤
free(ptr);
return 0;
}
解決方法: 配置後檢查是否為 NULL。
修正版:
struct Data {
int id;
};
int main() {
struct Data *ptr = (struct Data*)malloc(sizeof(struct Data));
if (ptr == NULL) {
printf("記憶體配置失敗。
");
return 1;
}
ptr->id = 10;
printf("ID: %d
", ptr->id);
free(ptr); // 釋放記憶體
return 0;
}
錯誤3: 使用未初始化的指標
情況: 未初始化的指標具有不確定值,可能導致存取無效的記憶體位置,造成程式崩潰。
錯誤範例:
struct Data {
int id;
};
int main() {
struct Data *ptr; // 未初始化
ptr->id = 10; // 錯誤發生
return 0;
}
解決方法: 使用前務必將指標初始化為 NULL 或配置有效的記憶體。
修正版:
struct Data {
int id;
};
int main() {
struct Data *ptr = NULL; // 初始化
printf("指標尚未初始化。
");
return 0;
}
提升安全性的撰寫技巧
1. 避免記憶體洩漏
- 動態配置的記憶體必須在使用後呼叫
free()
釋放。 - 養成在函式結束前釋放資源的習慣。
範例:
struct Data *ptr = (struct Data*)malloc(sizeof(struct Data));
// 使用後釋放
free(ptr);
2. NULL 指標檢查
透過統一的檢查流程,提升程式安全性。
範例:
if (ptr == NULL) {
printf("錯誤: 指標為 NULL。
");
return;
}
3. 善用靜態分析工具
使用工具自動檢查程式碼,避免錯誤與記憶體洩漏。
推薦工具:
- Valgrind(檢測記憶體洩漏)
- Cppcheck(靜態程式碼分析)

6. 常見問題(FAQ)
Q1. 點運算子與箭頭運算子要如何區分使用?
A: 點運算子(.
)與箭頭運算子(->
)都能存取結構體成員,但用法不同。
- 點運算子(
.
) 用於直接操作結構體變數。
struct Person {
char name[20];
int age;
};
struct Person p = {"Alice", 25};
printf("%s
", p.name); // 使用點運算子
- 箭頭運算子(
->
) 用於透過結構體指標操作成員。
struct Person p = {"Alice", 25};
struct Person *ptr = &p;
printf("%s
", ptr->name); // 使用箭頭運算子
區分重點:
- 若是直接操作結構體變數,使用「點運算子」。
- 若是透過指標存取成員,使用「箭頭運算子」。
Q2. 箭頭運算子能用在陣列嗎?
A: 箭頭運算子只能用於結構體指標,不能直接用於陣列。但若陣列的元素是結構體,就能搭配指標使用箭頭運算子。
範例: 陣列與箭頭運算子結合
#include <stdio.h>
#include <string.h>
struct Person {
char name[20];
int age;
};
int main() {
struct Person people[2] = {{"Alice", 25}, {"Bob", 30}};
struct Person *ptr = people;
printf("%s, %d
", ptr->name, ptr->age); // 使用箭頭運算子
ptr++; // 移動到下一個元素
printf("%s, %d
", ptr->name, ptr->age);
return 0;
}
執行結果:
Alice, 25
Bob, 30
因此,若陣列元素是結構體,就能透過指標與箭頭運算子存取。
Q3. 使用箭頭運算子時要注意什麼?
A: 使用箭頭運算子時,需特別注意以下幾點:
- 避免參照 NULL 指標:
務必確認指標不為 NULL。
if (ptr != NULL) {
ptr->age = 20;
}
- 檢查記憶體配置是否成功:
使用malloc
等函式後,要檢查指標是否為 NULL。
ptr = (struct Data*)malloc(sizeof(struct Data));
if (ptr == NULL) {
printf("記憶體配置失敗。
");
}
- 避免記憶體洩漏:
動態配置的記憶體,必須在使用後呼叫free()
釋放。
free(ptr);
Q4. 若結構體內包含指標,箭頭運算子要如何使用?
A: 當結構體內含指標時,依然可以使用箭頭運算子簡潔地存取資料。
範例: 結構體內含指標
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
int main() {
struct Node *head = (struct Node*)malloc(sizeof(struct Node));
head->data = 10;
head->next = NULL;
printf("Data: %d
", head->data); // 使用箭頭運算子
free(head); // 釋放記憶體
return 0;
}
執行結果:
Data: 10
這個範例展示了如何透過箭頭運算子,搭配結構體內部的指標,高效地存取資料。

7. 總結與後續學習步驟
箭頭運算子的重點回顧
本文詳細解說了 C 語言中的箭頭運算子(->
),從基礎到應用。以下重點整理:
- 箭頭運算子的角色與用法:
- 透過結構體指標存取成員的簡潔語法。
- 理解與點運算子(
.
)的差異,可正確選用。
- 具體應用範例:
- 鏈結串列與樹狀結構: 在資料結構操作中必不可少。
- 動態記憶體管理: 與
malloc
等函式結合,能撰寫更靈活的程式。
- 注意事項與錯誤對策:
- 避免 NULL 指標參照與記憶體洩漏: 本文提供了實際錯誤防範範例。
- 提升安全性的技巧: 建議使用靜態分析工具輔助。
- 常見問題(FAQ):
- 透過 QA 形式解答箭頭運算子的疑問,幫助讀者更深入理解。
建議的後續學習主題
若想進一步提升對箭頭運算子的理解,建議學習以下內容:
- 指標與結構體的進階應用:
- 多重指標、函式指標的進階程式設計。
- 透過動態陣列加強記憶體管理能力。
- C 語言的記憶體管理:
- 活用
calloc
、realloc
等函式。 - 避免記憶體洩漏與 Segmentation Fault 的除錯技巧。
- 資料結構與演算法:
- 鏈結串列、堆疊、佇列、樹等結構的設計與實作。
- 利用結構體設計排序與搜尋演算法。
- 程式最佳化:
- 效能提升與程式最佳化技巧。
- 程式碼審查與靜態分析工具的應用。
實作練習題與專案範例
為了更深入理解箭頭運算子,建議透過實作來強化學習:
- 鏈結串列操作:
- 實作新增、刪除、搜尋功能。
- 二元搜尋樹建立與搜尋:
- 利用遞迴實作插入與搜尋演算法。
- 鏈結佇列與堆疊:
- 結合動態記憶體配置設計高效資料結構。
- 檔案管理系統設計:
- 利用結構體與指標建立簡易資料庫應用。
最後
箭頭運算子是 C 語言中操作指標與結構體時不可或缺的工具。本文已從基礎用法到進階應用與注意事項進行完整介紹。
若要提升程式能力,最重要的是「動手寫程式」與「不斷測試、修正錯誤」。請善用本文範例,挑戰更高階的實作專案。
下一步,建議深入學習指標的進階應用與資料結構設計,這將幫助你培養更強的實戰開發能力。

8. 參考資料與延伸資源
線上資源
若想更深入學習 C 語言與箭頭運算子,以下線上資源值得參考:
- 手冊與參考文件
- 網站名稱: cppreference.com(英文)
- 內容: 提供 C 與 C++ 標準函式庫的完整參考,詳細介紹箭頭運算子與相關功能。
- 線上編譯器與除錯工具
- 網站名稱: OnlineGDB
- 內容: 可在瀏覽器中執行與除錯 C 程式,方便測試與修正錯誤。
書籍
若希望系統化提升 C 語言能力,以下書籍值得推薦:
- 作者: 柴田望洋
- 概要: 初學者必備的 C 語言基礎教材,詳細解說結構體與指標。
- 作者: 前橋 和彌
- 概要: 專注於指標的專業書籍,包含箭頭運算子的多種應用。
- 作者: Brian W. Kernighan, Dennis M. Ritchie
- 概要: C 語言的經典教材,深入學習指標與結構體。
範例程式下載
程式練習平台
- paiza Learning
- URL: https://paiza.jp
- 內容: 提供豐富的 C 語言實戰題庫,可透過解題強化程式能力。
- AtCoder
- URL: https://atcoder.jp
- 內容: 演算法與資料結構的競賽平台,題目中也包含箭頭運算子的實際應用。