在 C 中将数组和矩阵作为指针和指向指针的指针传递给函数 [英] Passing arrays and matrices to functions as pointers and pointers to pointers in C

查看:28
本文介绍了在 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;
}

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

I don't understand why I get this warning:

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

warning: passing argument 1 of ‘bar’ from incompatible pointer type

虽然 'foo' 调用似乎没问题.

Although 'foo' call seems to be ok.

谢谢:)

推荐答案

好吧,C 社区肯定不太了解它,通过浏览 SO 可以看出这一点.神奇的是,以下所有内容都是完全 100% 等效的:

Well, it's certainly not well understood by the C community as can be seen by glancing over SO. The magic is, all of the following are totally, 100%, equivalent:

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

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

It is very important to draw the distinction of a pointer and an array. An array is not a pointer. An array can be converted to a pointer to its first element. If you have a pointer you have this:

--------
| ptr  |  -------> data
--------

然而,如果你有一个数组,你就有这个:

However, if you have an array, you have this:

---------------------------
| c1 | c2 | c3 | ... | cn |
---------------------------

通过指针,数据位于另一个星球,但由指针链接.数组本身具有数据.现在,多维数组只是数组的数组.数组嵌套在父数组中.所以,你的数组的 sizeof 是:

With the pointer, the data is at a whole other planet, but linked to by the pointer. An array has the data itself. Now, a multi-dimensional array is just an array of arrays. The arrays are nested into a parent array. So, the sizeof of your array is:

(sizeof(int) * 10) * 10

那是因为你有 10 个数组,它们都是 10 个整数的数组.现在,如果你想传递那个数组,它会被转换.但是为了什么?指向其第一个元素的指针.元素类型不是一个指针,而是一个数组.因此,您传递了一个指向 10 个 int 数组的指针:

That is because you have 10 arrays, all of which are arrays of 10 integers. Now, if you want to pass that array, it is converted. But to what? A pointer to its first element. The element type is not a pointer, but an array. As a consequence, you pass a pointer to an array of 10 int:

int (*)[10] // a pointer to an int[10]

它既不是 int* 的数组,也不是 int** 的数组.您可能会问为什么不将数组作为 int** 传递.这是因为编译器必须知道行长.如果你做一个array[1][0],编译器将寻址距离二维数组开头sizeof(int) * 10个字节的地方.它以指向数组的指针类型解码该信息.

It is neither a array of int*, nor a int**. You may ask why the array is not passed as an int**. It's because the compiler has to know the row-length. If you do an array[1][0], the compiler will address a place sizeof(int) * 10 bytes apart from the begin of the 2 dimensional array. It decodes that information in the pointer-to-array type.

因此,您必须在上述完全等效的函数原型之一中进行选择.当然,最后一个只是令人困惑.如果参数被声明为数组,编译器只是默默地忽略写入最外维的任何数字.所以我也不会使用倒数第二个版本.最好是使用第一个或第二个版本.重要的是要记住C 没有(真正的)数组参数!参数最终将是一个指针(在这种情况下是指向数组的指针).

So, you have to chose among one of the above fully equivalent function prototypes. Naturally, the last one is just confusing. The compiler just silently ignores any number written in the most outer dimension if a parameter is declared to be an array. So i would also not use the second last version. Best is to use the first or second version. What is important to remember is that C has no (real) array parameters! The parameter will be a pointer in the end (pointer to array in this case).

注意上面的多维情况如何类似于下面的退化一维情况.以下 4 个版本完全等效:

Note how the multi-dimensional case of above is similar to the degenerate, one dimensional case below. All of the following 4 versions are fully equivalent:

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

这篇关于在 C 中将数组和矩阵作为指针和指向指针的指针传递给函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆