數組和指針的關系比較密切,這裡再總結一下這個知識點。由問題引入話題:
1. char a[] 和char *a等價嗎?
不是。 數組定義char a[6]請求預留6個字元的位置,并用名稱a表示。也即:有一個用a辨別的位置,可以放入6個字元。 而指針聲明char *p :請求一個位置放置一個指針,用名稱p表示。這個指針可以指向任何字元或任何連續的字元,或者哪裡都不指。通過圖像來說明: 若有下面語句:它們在記憶體中的表現形式如下(當然,箭頭是我們人為添加的): 注意:數組不能被指派。但是指針可以。在使用指針過程中一定要清楚指針本身和指針指向的内容,尤其是指針運算。指針運算總是居于所指對象的大小的。 2. 如何了解“指針和數組等價”? 在C語言中知識指針算數和數組下标運算等價,指針和數組是不同的。那麼,在作為函數形參的數組和指針為何可以互換呢?其實,給函數傳入數組隻是一種便利的做法。在這個過程中,數組會馬上退化為指針,事實上,數組從來沒有被傳入函數。 例如:char a[] = "hello"; char *p = "world";
void fun(int a[]) {...}
在編譯器裡都被當做指針來處理。因為在傳入數組的時候,函數接受到的正是指針。 注意:這種轉換僅限于函數形參的聲明,在别的地方并不适用。
3. 如何動态配置設定數組? (1)動态配置設定一維數組:用指向malloc配置設定的記憶體的指針來高效模拟數組。 int *dArray = (int *)malloc(10 * sizeof(int)); (2)動态配置設定二維數組: 方法一:配置設定一個指針數組,然後把每個指針初始化為動态配置設定的“行”。
方法二:讓數組的内容連續。但在配置設定行的時候要使用一點指針運算:記憶體布局:int **arr1 = (int *)malloc(rows * sizeof(int *)); for (i = 0; i < rows; i++) { arr1[i] = (int *)malloc(cols * sizeof(int)); }
記憶體布局:int **arr2 = malloc(rows * sizeof(int *)); arr2[0] = malloc(rows * cols * sizeof(int)); for (i = 1; i<rows; i++) { arr2[i] = arr2[0] + i * cols; }
方法三:用一個動态配置設定的一維數組來模拟二維數組: int *arr3 = malloc(rows * cols * sizeof(int)); 但是在使用是偶必須手工計算下标,如:arr3[i * cols + j]通路第i、j個元素。 方法四:使用數組指針: int (*arr4)[COLS] = malloc(rows * sizeof(*arr4));
或,
int (*arr5)[ROWS][COLS] = malloc(sizeof(*arr5));
這種方法的文法比較可怕,并且運作時最多隻能确定一維。 4. 如何釋放前面動态配置設定的數組? 對于arr1和arr2:
for (i=0; i<rows; i++) free((void *)arr1[i]); free((void *)arr1);
注意:釋放的原則:每個malloc()都必須有一個對應的free();
5. 如何給函數傳遞一個二維數組? 數組退化為指針的規則不能遞歸應用。數組的數組(二維數組)退化為數組的指針,而不是指針的指針。 若想函數傳遞二維數組:
int arr[ROWS][COLS]; fun(arr);那麼,函數的聲明也必須比對:或者void fun(int a[][COLS]) {...}
void fun(itn (*pArr)[COLS]) /* pArr is a pointer to an array */ { ... }