簡體   English   中英

將數組和矩陣傳遞給函數作為指針和指向C中的指針

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM