首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> C 語言入門

C 語言進階指標技巧:從雙重指標到函數指標的實戰應用

     編輯:C 語言入門

前言

指標是 C 語言的靈魂,也是區分初學者與資深開發者的關鍵分水嶺。本文將系統梳理指標的進階用法,涵蓋指標算術、const 修飾規則、空指標防護、雙重指標操作字串陣列、void* 型別擦除、以及函數指標實現回調與策略模式等核心技術。透過完整的程式碼範例,助你掌握指標在實際專案中的靈活運用。

1. 指標基礎回顧與進階應用

1.1 指標交換數值與算術運算

指標最經典的應用是實現函數間的「傳址呼叫」。以下範例展示了 swap 函數如何透過指標交換兩個變數的值,同時演示指標的加減運算本質——步長由資料型別決定。

#include <stdio.h>

void swap(int *a, int *b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int main() {
    int a = 10;
    int *p = &a;
    printf("a = %d\n", *p);       // 透過指標讀取值
    printf("p = %p\n", (void*)p); // 輸出位址

    p = p + 1;                    // 指標 +1,位址增加 sizeof(int) 位元組
    printf("p + 1 = %p\n", (void*)p);
    p = p - 1;                    // 指標 -1,位址減少 sizeof(int) 位元組
    printf("p - 1 = %p\n", (void*)p);

    int b = 20;
    printf("a = %d, b = %d\n", a, b);
    swap(&a, &b);              // 傳遞位址,實現真正交換
    printf("a = %d, b = %d\n", a, b);
    return 0;
}

1.2 const 修飾指標的三種模式

const 與指標結合時,位置決定語意:

  • const int *p (或 int const *p): 指向常數的指標。無法透過 *p 修改值,但指標本身可指向別處。
  • int *const p: 常數指標。指標本身被鎖死不可改變指向,但可透過 *p 修改值。
  • const int *const p: 雙重鎖定,指標與指向值皆不可變。
const int *p1 = &a; // *p1 = 30; // 錯誤:不能修改值
p1 = &b;              // 正確:可改變指向

int *const p2 = &a;   // p2 = &b; // 錯誤:不能改變指向
*p2 = 40;             // 正確:可修改值

1.3 空指標防護與野指標避免

指標用完後立即置 NULL,配合 if (p) 判斷,是防禦性程式設計的良好習慣,能有效避免野指標導致的未定義行為。

p = NULL;
if (p) printf("p = %p\n", (void*)p); // 條件為假,不會執行,保證安全

2. 雙重指標與字串陣列操作

雙重指標 (char **) 常用於操作「指標陣列」,即字串陣列。陣列名 name 退化為指向首元素的指標 (char **),透過 p[i] 即可存取每個字串。

#include <stdio.h>

int main() {
    char *name[] = {"zhangsan", "lisi", "wangwu", "zhaoliu"};
    char **p = name; // 雙重指標指向指標陣列

    for (int i = 0; i < 4; i++)
        printf("%s\n", p[i]); // p[i] 等價於 name[i]
    return 0;
}

3. 雙重指標實戰:字串轉整數解析器

利用雙重指標作為「輸出型參數」,函數可修改主調函數中的指標指向,實現「消費字串」的效果:解析前導數字,並將指標推進至第一個非數字字符。

#include <stdio.h>

int convert(char **str) {
    int num = 0;
    while (**str) {
        if (**str >= '0' && **str <= '9')
            num = num * 10 + **str - '0';
        else
            break;
        (*str)++; // 移動主調函數中的指標
    }
    return num;
}

int main() {
    char str[] = "1234abc";
    char *p = str;
    printf("%d\n", convert(&p)); // 輸出 1234
    printf("%s\n", p);             // 輸出 abc (指標已移動)
    return 0;
}

4. 萬用指標 void* 的型別擦除與還原

void* 可接受任意型別指標,但解引用前必須強制轉型。這是實現泛型介面(如 qsort, memcpy)的基石。

#include <stdio.h>

int main() {
    int a = 10;
    int *p = &a;
    void *p1 = p;          // 隱式轉換為 void*

    // *p1 = 20;           // 錯誤:void* 無法直接解引用
    *(int*)p1 = 20;        // 正確:先轉型為 int* 再解引用
    printf("a = %d\n", *(int*)p1);
    return 0;
}

5. 函數指標:實現回調與策略模式

5.1 基礎語法與最大/最小值切換

函數指標變數宣告語法:返回型別 (*指標名)(參數列表)。透過指標呼叫函數,可在執行期動態決定行為。

#include <stdio.h>

int min(int *buf, int size) {
    int m = buf[0];
    for (int i = 0; i < size; i++) if (buf[i] < m) m = buf[i];
    return m;
}
int max(int *buf, int size) {
    int m = buf[0];
    for (int i = 0; i < size; i++) if (buf[i] > m) m = buf[i];
    return m;
}

int main() {
    int data[10] = {1,2,3,4,5,6,7,8,9,0};
    int (*p)(int*, int); // 宣告函數指標

    p = min;
    printf("min = %d\n", p(data, 10)); // 透過指標呼叫 min
    p = max;
    printf("max = %d\n", p(data, 10)); // 透過指標呼叫 max
    return 0;
}

5.2 進階應用:通用排序框架

將比較規則抽象為函數指標傳入排序函數,分離演算法邏輯與業務規則,實現「策略模式」。

#include <stdio.h>

void print(int *a, int n) {
    for (int i = 0; i < n; i++) printf("%d ", a[i]);
    printf("\n");
}

// 比較規則:升序
int rule1(int x, int y) { return x - y; }
// 比較規則:降序
int rule2(int x, int y) { return y - x; }
// 比較規則:按模 3 餘數排序
int rule3(int x, int y) { return x % 3 - y % 3; }

// 通用氣泡排序
void sort(int *a, int n, int (*f)(int, int)) {
    for (int i = 0; i < n - 1; i++)
        for (int j = 0; j < n - 1 - i; j++)
            if (f(a[j], a[j+1]) > 0) { // 透過函數指標呼叫比較規則
                int t = a[j]; a[j] = a[j+1]; a[j+1] = t;
            }
}

int main() {
    int a[10] = {1,2,3,4,5,6,7,8,9,0};
    print(a, 10);
    sort(a, 10, rule1); print(a, 10); // 升序
    sort(a, 10, rule2); print(a, 10); // 降序
    sort(a, 10, rule3); print(a, 10); // 自訂規則
    return 0;
}

總結

指標進階技術是 C 語言高效、靈活程式設計的基石。掌握 const 語意、雙重指標操作動態資料結構、void* 實現泛型、函數指標實現回調與策略模式,將讓你能編寫出更健壯、可複用的系統級程式碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved