[英]Passing arrays and matrices to functions as pointers and pointers to pointers in C
給出以下代碼:
void
foo( int* array )
{
// ...
}
void
bar( int** matrix )
{
// ...
}
int
main( void ) {
int array[ 10 ];
int matrix[ 10 ][ 10 ];
foo( array );
bar( matrix );
return 0;
}
我不明白為什么我會收到這個警告:
警告:從不兼容的指針類型傳遞'bar'的參數1
雖然'foo'電話似乎沒問題。
謝謝 :)
嗯,通過瀏覽SO可以看出,C社區肯定不太了解它。 神奇之處在於, 以下所有內容均為100%,相當於 :
void foo(int (*array)[10]);
void foo(int array[][10]);
void foo(int array[10][10]);
void foo(int array[42][10]);
繪制指針和數組的區別非常重要。 數組不是指針 。 可以將數組轉換為指向其第一個元素的指針。 如果你有一個指針你有這個:
--------
| ptr | -------> data
--------
但是,如果你有一個數組,你有這個:
---------------------------
| c1 | c2 | c3 | ... | cn |
---------------------------
使用指針,數據位於整個另一個行星上,但由指針鏈接。 數組本身就有數據。 現在, 多維數組只是一個數組數組。 這些數組嵌套在父數組中。 所以,你的數組的sizeof是:
(sizeof(int) * 10) * 10
那是因為你有10個數組,所有數組都是10個整數的數組。 現在,如果要傳遞該數組,則將其轉換。 但到了什么? 指向其第一個元素的指針。 元素類型不是指針,而是數組。 因此,您將指針傳遞給10 int的數組:
int (*)[10] // a pointer to an int[10]
它既不是int*
的數組,也不是int**
。 您可能會問為什么數組不作為int**
傳遞。 這是因為編譯器必須知道行長度。 如果你做一個array[1][0]
,編譯器將尋址一個sizeof(int) * 10
個字節,距離2維數組的開頭。 它以指針到數組類型解碼該信息。
因此,您必須選擇上述完全等效的函數原型之一。 當然,最后一個只是令人困惑。 如果將參數聲明為數組,編譯器會默默地忽略在最外層維度中編寫的任何數字。 所以我也不會使用倒數第二個版本。 最好是使用第一個或第二個版本。 重要的是要記住C沒有(真正的)數組參數 ! 該參數將是最后的指針(在這種情況下指向數組的指針)。
注意上面的多維情況如何類似於下面的簡並一維情況。 以下所有4個版本完全等效:
void foo(int *array);
void foo(int array[]);
void foo(int array[10]);
void foo(int array[42]);
在C中傳遞多維數組是一個棘手的主題。 請參閱此常見問題
要問的問題是你將如何使用bar
。 如果你總是知道它將被傳遞一個10x10數組然后重寫為
bar(int matrix[10][10]);
如果你想處理不同維度的數組,那么你可能需要傳入長度:
bar(int *matrix, int width, int height);
問題是數據結構矩陣[10] [10]實際上不是指向數組[10]的十個指針的表,但它是一個包含100個整數的順序數組。 酒吧的正確簽名是
bar (int matrix[10][10])
如果你真的想使用間接表示矩陣並且使用int **矩陣作為bar的參數類型,那么你需要以不同的方式分配它:
int *matrix[10];
int my_data[100];
int i;
for (i = 0; i < 10; i++) { matrix[i] = &(my_data[i * 10]); }
bar(matrix);
現在'矩陣'匹配int **類型。 'matrix'是一個由十個指針組成的數組,你可以通過指針傳遞它,從而得到第二個*。
下面是一些要練習的代碼 - 它包含了傳遞二維數組和訪問元素值的代碼的所有可能類型
#include <stdio.h>
#define NUMROWS 2
#define NUMCOLUMNS 5
#define FILL_ARRAY() \
*array[0] = '1'; \
(*array)[7] = '2'; \
*(array[1]) = '3'; \
*(*(array+1)+1) = '4'; \
*(array[0]+3) = '5'; \
*(*array+2) = '7'; \
array[0][1] = '6';
void multi_01( char (*array)[NUMCOLUMNS] ) { FILL_ARRAY(); }
void multi_02( char array[][NUMCOLUMNS] ) { FILL_ARRAY(); }
void multi_03( char array[NUMROWS][NUMCOLUMNS] ) { FILL_ARRAY(); }
void multi_04( char **array ) { FILL_ARRAY(); }
void multi_05( char *array[] ) { FILL_ARRAY(); }
void multi_06( char *array[NUMCOLUMNS] ) { FILL_ARRAY(); }
int main(int argc, char **argv)
{
int i;
char mystr[NUMROWS][NUMCOLUMNS] = { { 'X', 'X', 'X', 'X'}, {'X','X','X'} };
char *pmystr[sizeof(mystr)/sizeof(*mystr)];
int numcolumns = sizeof(*mystr);
int numrows = sizeof(mystr)/sizeof(*mystr);
for( i=0; i<numrows; i++ ) pmystr[i] = *(mystr+i);
multi_01( mystr ); multi_02( mystr ); multi_03( mystr );
multi_04( pmystr ); multi_05( pmystr ); multi_06( pmystr );
printf("array '%s', '%s'\n", mystr[0], mystr[1]);
getc(stdin);
return 0;
}
您應該將欄定義為:
bar( int* matrix )
在C中,所有數組都應該作為int*
(或其他類型的type_of_element*
)傳遞。
如果你的數據確實是一個指針數組,那么int **
就可以了。 int[*data[]
例如。 這就是你在main(int argc, char *argv[])
得到的東西main(int argc, char *argv[])
。
int **matrix
表示你有一個指向int的指針。 這通常用於指示指向指針數組(也稱為向量)的指針。 絕對不是這樣的
int matrix[10][10]
這是一個指向單個內存部分的指針,大小為10x10整數。 嘗試更改為:
void bar(int *matrix[])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.