數組作為形參的使用
來源:https://www.cnblogs.com/weixiaoyu/p/4371806.html
1、對於一維數組來說,數組作為函數參數傳遞,實際上傳遞了一個指向數組的指針,在c編譯器中,當數組名作為函數參數時,在函數體內數組名自動退化為指針。此時調用函數時,相當於傳址,而不是傳值,會改變數組元素的值。
例如:void fun(int a[]); 若在fun函數中有a[i]++;等語句,那麽對應的數組元素會被修改,調用時直接用fun(a);即可。
2、對於高維數組來說,可以用二維數組名作為實參或者形參,在被調用函數中對形參數組定義時可以指定所有維數的大小,也可以省略第一維的大小說明,如:
void fun(int array[3][10]);
void fun(int array[][10]);
二者都是合法而且等價,但是不能把第二維或者更高維的大小省略,如下面的定義是不合法的:
void fun(int array[][]);
因為從實參傳遞來的是數組的起始地址,在內存中按數組排列規則存放(按行存放),而並不區分行和列,如果在形參中不說明列數,則系統無法決定應為多少行多少列,不能只指定一維而不指定第二維,下面寫法是錯誤的:
void fun(int array[3][]);
實參數組維數可以大於形參數組,例如形參數組定義為:
void fun(int array[3][10]);
而實參數組定義為:
int array[5][10];
這時形參數組只取實參數組的一部分,其余部分不起作用。
可以看到,將二維數組當作參數的時候,必須指明所有維數大小或者省略第一維的,但是不能省略第二維或者更高維的大小,這是由編譯器原理限制的。學編譯原理的時候應該 知道編譯器是這樣處理數組的:
對於數組 int p[m][n];
如果要取p[i][j]的值(i>=0 && i<m && 0<=j && j < n),編譯器是這樣尋址的,它的地址為:
p + i*n + j;
從以上可以看出,如果我們省略了第二維或者更高維的大小,編譯器將不知道如何正確的尋址,即這裏的n值是在形參定義的時候就要明確知道的。但是我們在編寫程序的時候卻需要用到各個維數都不固定的二維數組 作為參數,這就難辦了,編譯器不能識別阿,怎麽辦呢?不要著急,編譯器雖然不能識別,但是我們完全可以不把它當作一個二維數組,而是把它當作一個普通的指針,再另外加上兩個參數指明各個維數,然後我們為二維數組手工尋址,這樣就達到了將二維數組作為函數的參數傳遞的目的,根據這個思想,我們可以把維數固定 的參數變為維數隨即的參數,例如:
void fun(int array[3][10]);
void fun(int array[][10]);
變為:
void fun(int **array, int m, int n);
在轉變後的函數中,array[i][j]這樣的式子是不對的(不信,大家可以試一下),因為編譯器不能正確的為它尋址,所以我們需要模仿編譯器的行為把array[i][j]這樣的式子手工轉變為:
*(*array + n*i + j);
在調用這樣的函數的時候,需要註意一下,如下面的例子:
int a[3][3] = { {1, 1, 1}, {2, 2, 2}, {3, 3, 3}};
fun(a, 3, 3);
根據不同編譯器不同的設置,可能出現warning 或者error,可以進行強制轉換如下調用:
fun((int**)a, 3, 3);
數組作為形參的使用