文章目錄
- 一級指針
- 指針基本概念
- 指針使用示例
- 代碼說明
- 二、二級指針
- 二級指針重點解析
一級指針
C語言中的指針是一個非常重要的概念,它存儲了變量的內存地址。指針的使用可以使程序更加高效,尤其在處理數組、字符串和動態內存分配時。
指針基本概念
- 指針變量:用于存儲內存地址的變量
- 取地址符
&
:獲取變量的內存地址 - 解引用符
*
:訪問指針所指向地址的內容
指針使用示例
下面是一些常見的指針使用示例:
可以運行
#include <stdio.h>// 1. 基本指針操作
void basicPointerExample() {int num = 10;int *p; // 聲明一個int類型的指針p = # // 將num的地址賦值給指針pprintf("num的值: %d\n", num);printf("num的地址: %p\n", &num);printf("指針p存儲的地址: %p\n", p);printf("指針p指向的值: %d\n", *p);*p = 20; // 通過指針修改num的值printf("修改后num的值: %d\n", num);
}// 2. 指針作為函數參數(實現值的交換)
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}// 3. 指針與數組
void pointerAndArray() {int arr[] = {1, 2, 3, 4, 5};int *p = arr; // 數組名本身就是第一個元素的地址printf("\n數組元素: ");for(int i = 0; i < 5; i++) {// 以下兩種方式等價printf("%d ", *(p + i));// printf("%d ", arr[i]);}printf("\n");
}// 4. 指針與字符串
void pointerAndString() {char *str = "Hello, World!"; // 字符串指針printf("\n字符串內容: ");// 使用指針遍歷字符串while(*str != '\0') {printf("%c", *str);str++; // 指針自增,指向 next 字符}printf("\n");
}// 5. 指針數組
void pointerArray() {char *names[] = {"Alice", "Bob", "Charlie", "David"};printf("\n指針數組中的字符串: ");for(int i = 0; i < 4; i++) {printf("%s ", names[i]);}printf("\n");
}int main() {basicPointerExample();int x = 100, y = 200;printf("\n交換前: x = %d, y = %d\n", x, y);swap(&x, &y);printf("交換后: x = %d, y = %d\n", x, y);pointerAndArray();pointerAndString();pointerArray();return 0;
}
代碼說明
- 基本指針操作:展示了如何聲明指針、獲取變量地址、通過指針訪問和修改變量值
- 指針作為函數參數:通過指針在函數內部修改外部變量的值,實現了兩個數的交換
- 指針與數組:數組名本質上是指向第一個元素的指針,演示了如何通過指針訪問數組元素
- 指針與字符串:字符串可以用指針表示,演示了如何通過指針遍歷字符串
- 指針數組:數組中的每個元素都是指針,這里用指針數組存儲多個字符串
指針的使用需要特別注意避免空指針、野指針等問題,這些可能會導致程序崩潰或不可預期的行為。正確使用指針可以使C程序更加靈活和高效。
二、二級指針
在C語言中,二級指針是指向指針的指針,它存儲的是另一個指針變量的地址。二級指針在處理指針數組、動態二維數組以及需要修改指針本身的場景中非常有用。
下面在原有代碼基礎上添加二級指針的使用示例:
#include <stdio.h>
#include <stdlib.h> // 用于動態內存分配// 1. 基本指針操作
void basicPointerExample() {int num = 10;int *p; // 聲明一個int類型的指針p = # // 將num的地址賦值給指針pprintf("num的值: %d\n", num);printf("num的地址: %p\n", &num);printf("指針p存儲的地址: %p\n", p);printf("指針p指向的值: %d\n", *p);*p = 20; // 通過指針修改num的值printf("修改后num的值: %d\n", num);
}// 2. 指針作為函數參數(實現值的交換)
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}// 3. 指針與數組
void pointerAndArray() {int arr[] = {1, 2, 3, 4, 5};int *p = arr; // 數組名本身就是第一個元素的地址printf("\n數組元素: ");for(int i = 0; i < 5; i++) {// 以下兩種方式等價printf("%d ", *(p + i));// printf("%d ", arr[i]);}printf("\n");
}// 4. 指針與字符串
void pointerAndString() {char *str = "Hello, World!"; // 字符串指針printf("\n字符串內容: ");// 使用指針遍歷字符串while(*str != '\0') {printf("%c", *str);str++; // 指針自增,指向 next 字符}printf("\n");
}// 5. 指針數組
void pointerArray() {char *names[] = {"Alice", "Bob", "Charlie", "David"};printf("\n指針數組中的字符串: ");for(int i = 0; i < 4; i++) {printf("%s ", names[i]);}printf("\n");
}// 6. 二級指針使用示例
void doublePointerExample() {int num = 100;int *p = # // 一級指針,指向numint **pp = &p; // 二級指針,指向指針pprintf("\n=== 二級指針基本操作 ===\n");printf("num的值: %d\n", num);printf("p指向的值: %d\n", *p);printf("pp指向的指針所指向的值: %d\n", **pp);printf("num的地址: %p\n", &num);printf("p存儲的地址: %p\n", p);printf("pp存儲的地址: %p\n", pp);printf("p本身的地址: %p\n", &p);
}// 7. 二級指針與指針數組
void doublePointerAndPointerArray() {char *languages[] = {"C", "Python", "Java", "JavaScript"};char **pp; // 二級指針,用于指向指針數組元素printf("\n=== 二級指針訪問指針數組 ===\n");// 二級指針遍歷指針數組pp = languages; // 指向數組首元素for(int i = 0; i < 4; i++) {printf("語言: %s, 地址: %p\n", *pp, pp);pp++; // 移動到下一個指針元素}
}// 8. 二級指針作為函數參數(修改指針本身)
void allocateMemory(int **ptr, int size) {// 為指針分配內存,需要二級指針才能修改外部指針*ptr = (int*)malloc(size * sizeof(int));if(*ptr == NULL) {printf("\n內存分配失敗!\n");return;}// 初始化分配的內存for(int i = 0; i < size; i++) {*(*ptr + i) = i * 10;}
}int main() {basicPointerExample();int x = 100, y = 200;printf("\n交換前: x = %d, y = %d\n", x, y);swap(&x, &y);printf("交換后: x = %d, y = %d\n", x, y);pointerAndArray();pointerAndString();pointerArray();// 演示二級指針doublePointerExample();doublePointerAndPointerArray();// 二級指針作為函數參數示例int *arr = NULL;allocateMemory(&arr, 5); // 傳遞指針的地址if(arr != NULL) {printf("\n通過二級指針分配的數組: ");for(int i = 0; i < 5; i++) {printf("%d ", arr[i]);}printf("\n");free(arr); // 釋放內存}return 0;
}
二級指針重點解析
-
二級指針的定義與初始化:
int num = 100; int *p = # // 一級指針 int **pp = &p; // 二級指針,指向指針p
這里
pp
就是二級指針,它存儲的是一級指針p
的地址。 -
二級指針的解引用:
*pp
:得到一級指針p
的值(即num
的地址)**pp
:通過兩次解引用,得到最終變量num
的值
-
二級指針的主要用途:
- 訪問指針數組:如示例中遍歷存儲字符串的指針數組
- 作為函數參數修改指針本身:當需要在函數內部為指針分配內存或修改指針指向時
- 處理動態二維數組:二級指針常用來表示動態分配的二維數組
-
使用注意事項:
- 二級指針也可能出現空指針問題,使用前需檢查
- 多級指針會增加代碼復雜度,應避免過度使用
- 動態分配內存后需記得釋放,防止內存泄漏
通過二級指針,我們可以更靈活地操作指針本身,這在處理復雜數據結構和動態內存分配時特別有用。