1、數組指針和指針數組的概念理解
數組指針:數組是修飾詞,指針是名詞,本質上是指針,可以理解為數組的指針,如:int (* arr) [10] 就是一個數組指針
指針數組:指針是修飾詞,數組是名詞,本質上是數組,可以理解為存放指針的數組,如:int* arr[10]; 一個指針數組。
2、指針和數組的關系
對於:int arr[10] 這樣一個一維數組,通常arr是數組首元素的地址,也就是 arr = & arr[0]; 代碼驗證如下:
1 #include <stdio.h> 2 3 int main() 4 { 5 int arr[10] = {0,1,2,3,4,5,6,7,8,9}; 6 printf("arr address = %p\n",arr); 7 printf("&arr[0] address = %p\n",&arr[0]); 8 9 return 0; 10 }
代碼運行結果為:
但arr並不是一直表示為首元素的地址,需要記住一個特列,sizeof(arr), 此時arr表示整個數組,用於sizeof來計算整個數組的大小
既然arr是首元素的地址,那么就可以賦值給指針去變量:如:int* p = arr; 代碼等價於 int * p = &arr[0];
為充分理解上述內容,下面來一段用指針來訪問數組的代碼:
#include <stdio.h> int main() { int arr[] = {0,1,2,3,4,5}; int* p = arr; for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++){ printf("arr[%d] = %d ========= %d\n", i, arr[i], *(p + i)); } return 0; }
代碼運行結果為:
這里需要注意一個知識點:既然可以通過指針訪問數組,給出以下兩段代碼都可以訪問數組中的元素:
#include <stdio.h> #define NUM 5 int main() { //代碼 1 int arr[NUM] = {0,1,2,3,4}; printf("code 1:\n"); for (int* p = &arr[NUM]; p > arr;) { printf("%d ",*--p); } printf("\n"); //代碼 2 printf("code 2:\n"); for (int *p = &arr[NUM - 1]; p >= arr; p--) { printf("%d ",*p); } return 0; }
代碼運行結果為:
可以發現兩段代碼都對數組中的元素進行了訪問,但C語言標准規定了允許指向數組元素的指針可以和最后一個元素后面的內存位置進行指針比較,不允許與第一個元素之前的內存位置進行比較,所以,使用指針比較的時候應該注意符合語言規范,避免后期出現不可知問題,所以,上述代碼二屬於不規范代碼。
知識點:既然arr是數組首元素的地址,那么&arr的地址是誰的地址?
下面通過代碼驗證:
#include <stdio.h> #define NUM 2 int main() { int arr[NUM] = {1,2}; printf("arr = %p \n", arr); printf("&arr = %p \n", &arr); printf("arr + 1 = %p \n", arr + 1); printf("&arr + 1 = %p \n", &arr + 1); return 0; }
代碼運行結果為:
可以發現,arr和&arr的地址是相同的,但是arr+1的地址為0X0061FF1C, &arr + 1的地址為:0X0061FF20,比arr + 1的地址多出了4字節,這是因為&arr是整個數組的地址,數組的大小為8字節,所以,每次+1相當於加了8字節的地址,而arr是數組元素的地址,數組元素是int型,所以,每次+1地址加了4字節。
3、指針數組
前面已經說了,指針數組是存放指針的數組,所以指針數組的使用和整形數組一樣,只不過指針數組的元素內容為指針變量,而整形數組的元素內容為整形變量。
如:int arr[10];arr為整形數組,表示保存了10個int元素的數組,同理,int* arr[10]; arr為指針數組,表示保存了10個int*類型的數組
為理解指針數組,下面舉一指針數組的使用代碼例子:
#include <stdio.h> #define NUM 5 int main() { int arr1[NUM] = {1,2,3,4,5}; int arr2[NUM] = {6,7,8,9,10}; int arr3[NUM] = {10,11,12,13,14}; int* parr[] = {arr1, arr2, arr3}; for (int i = 0; i < 3; i++) { for (int j = 0; j < NUM; j++) { //以下四行代碼等價 //printf("%d ", *(parr[i] + j)); // printf("%d ", *(*(parr + i) + j)); //printf("%d ",parr[i][j]); printf("%d ", (*(parr + i))[j]);//這里注意,[]的優先級是高於*的,所以一定要在解引用前加個括號 } printf("\n"); } return 0; }
代碼運行結果為:
4、數組指針
數組指針是數組的指針,本質上是一個指針,用來保存數組的地址。形式:int (*parr)[10]; parr是數組的指針, [10]表示數組有十個元素,元素類型為int
比如,整形指針,int* p; p是一個整形指針,用於保存int類型的地址,同理,數組指針是用於保存數組的地址,如int (*parr)[10]數組指針可用於保存int arr[10]數組的指針,使用如下:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int (*parr)[10] = &arr; //&arr是數組的地址,int (*parr)[10]用於保存數組的地址。
再舉例:
int* arr[5];
—— = &arr;
——下划線處應該填寫什么內容呢? 要深入理解數組指針,首先,arr數組是保存5個int* 類型的數組,那么該數組指針首先應該確保數組元素的類型為int*,數組有5個元素,parr應該是數組指針,應該加括號,所以下划線處應該填寫 int* (*parr)[5] ;下圖詳細說明:
為理解數組指針,下面舉個例子,通過數組指針來訪問數組的元素
代碼運行結果為:
可以發現用數組指針去訪問一維數組里的元素非常別扭,確實經常也不這么用,實際寫代碼時,數組指針常用於二維數組,下篇就詳細說說二維數組和數組指針吧。