天天看點

深入學習C語言:指針的進階用法

作者:嵌入式講堂

嵌入式相關的技術知識

歡迎大家留言讨論,互相交流

關注号主,共同進步

如有錯誤歡迎指正

目錄

  1. 介紹指針的基礎用法
  2. 數組指針
  3. 指針數組
  4. 二級指針
  5. 函數指針
  6. 指針函數
  7. const指針的不同用法
  8. 總結

介紹指針的基礎用法

指針是C語言中最重要也最難了解的概念之一。在基礎使用方面,指針主要用于通路和操作變量的位址。例如,我們可以通過以下方式定義并使用一個指針:

int x = 1;
int* ptr = &x;
*ptr = 2;
printf("%d\n", x); // 輸出 2           

在上面的例子中,我們首先定義了一個整型變量x,然後使用&運算符擷取x的位址,并将其指派給指針ptr。接着,我們使用*運算符來通路指針所指向的變量,并将該變量的值修改為2。最後,我們使用printf函數輸出變量x的值,結果為2。

數組指針

數組指針是指針指向一個數組,使得指針可以像一個數組一樣來操作資料。例如:

int arr[3] = {1, 2, 3};
int (*pArr)[3]; // 定義一個指向數組類型的指針
pArr = &arr; // 指針pArr指向數組arr
(*pArr)[0] = 4; // 通路數組元素
printf("%d\n", arr[0]); // 輸出 4           

在上面的代碼中,我們首先定義了一個整型數組arr,然後定義了一個指向數組類型的指針pArr,并将其指向數組arr。接着,我們通過pArr指針來通路數組的元素,并修改了其中一個元素的值。最後,我們輸出數組的第一個元素,結果為4。

指針數組

指針數組是數組中的每個元素都是指針。通常我們使用指針數組來表示相同類型的元素。例如:

char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};           

在上面的例子中,days是一個指針數組,其中每個元素都是指向字元的指針。

指針數組常常與函數指針結合使用。例如,我們可以使用函數指針來實作一個簡單的電腦:

int add(int a, int b) {
    return a + b;
}

int sub(int a, int b) {
    return a - b;
}

int (*func_ptr[2])(int, int) = {add, sub};

int main() {
    int x = 1, y = 2;
    printf("%d\n", func_ptr[0](x, y));
    printf("%d\n", func_ptr[1](x, y));
    return 0;
}           

在上面的示例中,我們定義了一個存儲函數指針的指針數組func_ptr,其中包含兩個函數指針add和sub。接着,我們定義了兩個整型變量x和y,并在main函數中調用了數組中的函數指針來進行加減運算。

二級指針

二級指針是指針的指針。在需要動态配置設定記憶體和傳遞指針時,二級指針可以更友善地實作。下面是一個使用二級指針來交換變量值的示例:

void swap(int** x, int** y) {
    int* tmp = *x;
    *x = *y;
    *y = tmp;
}

int main() {
    int x = 1, y = 2;
    int* ptr_x = &x;
    int* ptr_y = &y;
    swap(&ptr_x, &ptr_y);
    printf("x = %d, y = %d\n", *ptr_x, *ptr_y);
    return 0;
}           

在上面的示例中,函數swap的參數類型是二級指針,可以在内部交換兩個指針的值,達到交換變量的效果。

函數指針

函數指針是指向函數的指針變量。在實際開發過程中,我們常常需要通過函數指針來實作回調函數方法。下面是一個簡單的示例:

void say_hello() {
    printf("Hello, World!\n");
}

void execute(void (*f)()) {
    f();
}

int main() {
    execute(say_hello);
    return 0;
}           

在上面的代碼中,我們定義了一個函數say_hello用于輸出"Hello, World!"。接着,我們定義了一個名為execute的函數,其參數類型為函數指針void (*f)(),表示參數是一個不傳回值且沒有參數的函數指針。在main函數中,我們調用execute函數并傳入say_hello函數的函數指針作為參數,程式輸出"Hello, World!"。

指針函數

指針函數是傳回指針類型值的函數。使用指針函數可以友善地擷取函數内部申請的記憶體位址,并将其傳遞到程式的其他部分。下面是一個簡單的示例:

char* get_memory(int size) {
    char* ret = (char*) malloc(size);
    return ret;
}

int main() {
    char* str = get_memory(strlen("Hello, World!") + 1);
    strcpy(str, "Hello, World!");
    printf("%s\n", str);
    free(str);
    return 0;
}           

在上面的代碼中,我們定義了一個指針函數get_memory,該函數申請了一塊記憶體并傳回一個指向該記憶體的指針。在main函數中,我們調用get_memory函數并傳入需要申請的記憶體大小。接着,我們使用strcpy函數将字元串"Hello, World!"複制到申請的記憶體空間中,并輸出該字元串。最後,我們釋放了申請的記憶體空間。

const指針的不同用法

const指針是指一個指向常量的指針,即指針所指向的值不能被修改。它可以有以下幾種用法:

  • const int *ptr:指向常量的指針,指針指向的值不能被修改。
  • int *const ptr:指向變量的常量指針,指針本身的值不能被修改。
  • const int *const ptr:指向常量的常量指針,指針本身的值和指針指向的值都不能被修改。

例如,下面的代碼定義了一個指向整數變量a的常量指針,以及一個指向常量整數b的指針:

int a = 1;
const int b = 2;

const int *ptr1 = &a;
int *const ptr2 = (int *)&b;
const int *const ptr3 = &b;           

在使用const指針時,需要注意以下幾點:

  • 指針所指向的值不能被修改。
  • 需要使用強制類型轉換來繞過const限制。
// 使用const指針
*ptr1 = 2; // 錯誤,不能修改指針所指向的值
*ptr2 = 3; // 正确,可以修改指針所指向的值
ptr3 = &a; // 錯誤,不能修改指針本身的值

// 繞過const限制
*(int *)&b = 3;           

總結

指針作為一種強大的工具,具有很多複雜的使用方法。掌握了這些進階用法,可以更好地了解和使用C語言,進一步提高程式的品質和效率。在實際開發過程中,根據具體的業務場景和需求,靈活使用指針的各種進階用法,可以讓我們寫出更加高效和可靠的程式。

歡迎來到【嵌入式講堂】

專注嵌入式技術交流

作業系統,算法,程式設計語言知識分享

歡迎大家一起讨論,讓我們共同進步

繼續閱讀