C语言-二维数组做函数的参数
文章目錄
- 1 引例
- 2 觀點1 這種使用方法是錯誤的
- 3 觀點2 根本不需要這么做
- 4 二維數組做函數參數的方法
- 4.1 方法1
- 4.2 方法2
- 4.3 方法3
- 5 與Java的不同
1 引例
下面的程序很簡單,定義了一個PrintMatrix函數將一個二維數組以矩陣的形式打印出來。
#include <stdio.h> #define SIZE (4)void PrintMatrix(int **arr) {for (int i = 0; i < SIZE; i++) {for (int j = 0; j < SIZE; j++) {printf(" %d", arr[i][j]);}printf("\n");} }int main(void) {int matrix[SIZE][SIZE] = {{1, 2, 3, 4},{5, 6, 7, 8},{1, 2, 3, 4},{5, 6, 7, 8}};PrintMatrix(matrix);return 0; }當我們編譯這個程序的時候會出現下面的錯誤信息:
error: cannot convert 'int (* )[4]' to 'int**'按理來說,一維數組對應著一級指針,就像我們經常使用的,作為函數參數的時候也不理外:
int arr[4] = {1, 2, 3, 4}; int *p = arr;那么二維數組對應著二級指針怎么就出錯了呢?
要想解釋清楚這個問題,首先需要知道二級指針和二維數組的定義:
- 二維數組:二維數組本質上是以數組作為數組元素的數組,即“數組的數組”;
- 二級指針:指向指針的指針。
下面將會從兩種觀點來分析這個問題。
2 觀點1 這種使用方法是錯誤的
舉一個簡單的例子,定義一個二維數組。
int a[2][2] = {1, 2, 3, 4};假如用一個二級指針指向它。
int **p = a;運行如下代碼(打印了a的值和a,a[0],a[0][0] 的地址):
printf("%#x \n", a);printf("%#x \n", &a);printf("%#x \n", &a[0]);printf("%#x \n", &a[0][0]);運行的結果是輸出的四行結果是完全一樣的(不同計算機輸出的地址可能不同):
0x9ffe40 0x9ffe40 0x9ffe40 0x9ffe40既然 int **p = a;,可以推出 p 保存的是 a[0][0] 的地址,那么用 * 號可以對其解引用指針而取出地址的內容,于是測試以下代碼:
printf("%d \n", *&a[0][0]);為 p 指針進行了一次解引用,和預期的一樣,輸出了二維數組 a 的第一個元素 1,理所當然的 p 是二級指針,那么也可以對其進行二次解引用,當我們對其進行二次解引用的時候,編譯器報錯了:
error: invalid type argument of unary '*' (have 'int')還有一點值得注意的是,在二維數組中,a + 1,可以移動一個元素的位置(也就是移動一個一維數組的大小),而用二級指針,p + 1 永遠移動一個 sizeof(int) 的大小(本例中)。
3 觀點2 根本不需要這么做
學過 C/C++ 的朋友應該都知道,一位數組在內存中是線性排列的,那么二維數組也不理外,它也是線性排列的。
假如只知道 arr 的地址,那么能得到 arr[1][1] 的地址嗎?
答案是可以的,因為數組在內存中是線性排列,那么就代表著只要知道數組的起始地址,就可以通過一次取址獲得任意元素的位置,所以根本不需要二次取址。
這也就解釋了為什么聲明二維數組的時候,編譯器根本“不關心”一維的大小,以至于可以省略掉它,如:
int a[][2];4 二維數組做函數參數的方法
4.1 方法1
void fun(int arr[2][2]);這種方法導致只能處理2行2列的int型數組,即固定了數組大小。
4.2 方法2
void fun(int arr[][2]);可以省略一維的大小,這種方法的限制略微寬松了一些,但是還是只能處理每行是2個整數長度的數組。
4.3 方法3
void fun(int (*arr)[2]);這個方法需要重點討論,這里引入了一個新的概念叫做數組指針。
int (*arr)[2];在解釋這個概念之前要比較一下數組指針和指針數組的不同,以防止混淆:
- 指針數組(array of pointers):即用于存儲指針的數組,也就是數組元素都是指針,如 int* a[4],表示數組 a 中的元素都為 int 型指針;
- 數組指針(a pointer to an array):即指向數組的指針,如 int (*a)[4],表示指向數組 a 的指針。
通過上述概念就知道了應該用數組指針指向一個二維數組,以下是正確的示例:
int a[2][2] = {1, 2, 3, 4}; int (*p)[2] = a;5 與Java的不同
Java中聲明一個二維數組:
int[][] arr = new int[2][2];不同于 C/C++ 中的:
int arr[2][2];也不同與 C/C++ 中的:
int (*p)[2] = new int[2][2];在 Java 中則是分配了一個包含 2 個指針的數組,指針數組的每個元素包含一個一維數組,在 C++ 中的聲明如下:
int **p = new int *[2];總結
以上是生活随笔為你收集整理的C语言-二维数组做函数的参数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 逆向
- 下一篇: C语言-什么是尾递归