在C语言中,将数组和矩阵作为指针和指向指针的指针传递给函数

在C语言中,将数组和矩阵作为指针和指向指针的指针传递给函数,c,pointers,parameters,C,Pointers,Parameters,给定以下代码: 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

给定以下代码:

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”这个电话似乎还可以


谢谢:)

您应该将bar定义为:

bar( int* matrix )
在C中,所有数组都应作为
int*
(或
type\u元素*
传递给其他类型)


int**
如果您的数据实际上是一个指针数组,那么就可以了<例如,code>int[*data[]这就是您在
main(int-argc,char*argv[])
中得到的结果。问题是数据结构矩阵[10][10]实际上不是一个包含指向数组[10]的十个指针的表,而是一个包含100个整数的序列数组。正确的bar签名是

bar (int matrix[10][10])
如果您确实希望使用间接方式表示矩阵,并将int**matrix作为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*矩阵[10];
int my_数据[100];
int i;
对于(i=0;i<10;i++){matrix[i]=&(my_data[i*10])}而言
棒(矩阵);

现在“matrix”与int**类型匹配。“matrix”是一个由十个指针组成的数组,您可以通过指针传递它,因此在C中传递多维数组是一个棘手的问题。请参阅

要问的问题是如何使用
bar
。如果您总是知道它将被传递一个10x10数组,那么将其重写为

bar(int matrix[10][10]);
如果要处理不同尺寸的数组,则可能需要传递长度:

bar(int *matrix, int width, int height);
表示您有一个指向int的指针。这通常用于表示指向指针数组(也称为向量)的指针。对于

int matrix[10][10]
这更像是指向大小为10x10 int的单个内存段的指针。请尝试更改为:

void bar(int *matrix[])

当然,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 |
---------------------------
但是,如果您有一个数组,则有:

--------
| ptr  |  -------> data
--------
---------------------------
| c1 | c2 | c3 | ... | cn |
---------------------------
使用指针,数据位于另一个星球上,但通过指针链接。数组本身就有数据。现在,多维数组只是数组的数组。数组嵌套在父数组中。因此,数组的大小为:

(sizeof(int) * 10) * 10
这是因为您有10个数组,所有数组都是10个整数的数组。现在,如果要传递该数组,它将被转换为什么?指向其第一个元素的指针。元素类型不是指针,而是数组。因此,您传递指向10个整数数组的指针:

int (*)[10] // a pointer to an int[10]
它既不是
int*
数组,也不是
int**
。您可能会问,为什么该数组不作为
int**
传递。这是因为编译器必须知道行长度。如果执行
数组[1][0]
,编译器将寻址
sizeof(int)的位置*10
距离二维数组开头的字节。它在指向数组类型的指针中解码该信息

因此,您必须从上述完全等效的函数原型中选择一个。自然,最后一个是令人困惑的。如果一个参数被声明为数组,编译器只是默默地忽略在最外层维度中写入的任何数字。因此,我也不会使用最后第二个版本。最好使用第一个或第二个版本。Wh至少要记住,C没有(实数)数组参数!该参数最后将是一个指针(在本例中是指向数组的指针)

请注意,上面的多维情况与下面的退化一维情况是如何相似的。以下4个版本完全等效:

void foo(int *array);
void foo(int array[]);
void foo(int array[10]);
void foo(int array[42]);

下面是一些需要练习的代码——它包含所有可能的传递二维数组的类型和访问元素值的代码

#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;
}
#包括
#定义NUMROWS 2
#定义numcolumn 5
#定义填充数组()\
*数组[0]=“1”\
(*数组)[7]=“2”\
*(数组[1])='3'\
*(*(数组+1)+1)='4'\
*(数组[0]+3)='5'\
*(*数组+2)='7'\
数组[0][1]=“6”;
void multi_01(char(*array)[NUMCOLUMNS]){FILL_array();}
void multi_02(字符数组[][NUMCOLUMNS]){FILL_数组();}
void multi_03(字符数组[NUMROWS][NUMCOLUMNS]){FILL_数组();}
void multi_04(字符**数组){FILL_数组();}
void multi_05(char*array[]){FILL_array();}
void multi_06(char*数组[NUMCOLUMNS]){FILL_数组();}
int main(int argc,字符**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);

对于(i=0;i),问题在于数据结构矩阵[10][10]实际上不是一个包含指向数组[10]的十个指针的表,而是一个包含100个整数的序列数组这就是为什么我如此困惑的原因!虽然Mark Pim的答案完全集中在我问题的主要问题上,但我想通过将此答案设置为推荐答案,以某种方式补偿您试图在C中解释数组作为参数的所有努力。谢谢!您的答案很好。谢谢!bar的计算结果为int**matrix,而不是您的方式将通过矩阵