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

Aur*_*ron 15 c parameters pointers

给出以下代码:

void
foo( int* array ) 
{
    // ...
}

void
bar( int** matrix ) 
{
    // ...
}

int
main( void ) {
    int array[ 10 ];
    int matrix[ 10 ][ 10 ];

    foo( array );
    bar( matrix );

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么我会收到这个警告:

警告:从不兼容的指针类型传递'bar'的参数1

虽然'foo'电话似乎没问题.

谢谢 :)

Joh*_*itb 46

嗯,通过浏览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]);
Run Code Online (Sandbox Code Playgroud)

这是非常吸引的指针和数组的区别很重要.数组不是指针.可以将数组转换为指向其第一个元素的指针.如果你有一个指针你有这个:

--------
| ptr  |  -------> data
--------
Run Code Online (Sandbox Code Playgroud)

但是,如果你有一个数组,你有这个:

---------------------------
| c1 | c2 | c3 | ... | cn |
---------------------------
Run Code Online (Sandbox Code Playgroud)

使用指针,数据位于整个另一个行星上,但由指针链接.数组本身就有数据.现在,多维数组只是一个数组数组.这些数组嵌套在父数组中.所以,你的数组的sizeof是:

(sizeof(int) * 10) * 10
Run Code Online (Sandbox Code Playgroud)

那是因为你有10个数组,所有数组都是10个整数的数组.现在,如果要传递该数组,则将其转换.但到了什么?指向其第一个元素的指针.元素类型不是指针,而是数组.因此,您将指针传递给10 int的数组:

int (*)[10] // a pointer to an int[10]
Run Code Online (Sandbox Code Playgroud)

它不是一个阵列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]);
Run Code Online (Sandbox Code Playgroud)


Mar*_*Pim 15

在C中传递多维数组是一个棘手的主题.见这个FAQ.

要问的问题是你将如何使用bar.如果你总是知道它将被传递一个10x10数组然后重写为

bar(int matrix[10][10]);
Run Code Online (Sandbox Code Playgroud)

如果你想处理不同维度的数组,那么你可能需要传入长度:

bar(int *matrix, int width, int height);
Run Code Online (Sandbox Code Playgroud)


Ant*_*ima 6

问题是数据结构矩阵[10] [10]实际上不是指向数组[10]的十个指针的表,但它是一个包含100个整数的顺序数组.酒吧的正确签名是

bar (int matrix[10][10])
Run Code Online (Sandbox Code Playgroud)

如果你真的想使用间接表示矩阵并且使用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);
Run Code Online (Sandbox Code Playgroud)

现在'矩阵'匹配int**类型.'matrix'是一个由十个指针组成的数组,你可以通过指针传递它,从而得到第二个*.