将2维数组传递给函数的正确方法
我有一个2维数组,我将它传递给一个函数来执行某些操作。我想知道这样做的正确方法...将2维数组传递给函数的正确方法
#define numRows 3
#define numCols 7
#define TotalNum (numRows*numCols)
int arr[numRows][numCols] = {{0,1,2,3,4,5,6}, {7,8,9,10,11,12,13},{14,15,16,17,18,19,20}};
void display(int **p)
{
printf("\n");
for (int i = 0; i< numRows;i++)
{
for (int j = 0;j< numCols;j++)
{
printf("%i\t",p[i][j]);
}
printf("\n");
}
}
int main() {
display(arr);
}
我得到一个错误信息:
'display': cannot convert parameter1 from 'int' to 'int*'
这是传递一个2维数组到函数的正确方法?如果不是,那么正确的方法是什么?
如果(就像你的情况一样),你知道编译时数组的维数,你可以只写void display(int p[][numCols])
。
一些解释:你可能知道,当你将一个数组传递给一个函数时,你实际上传递了一个指向第一个成员的指针。在C语言中,二维数组只是一个数组的数组。因此,您应该将函数传递给2D数组中的第一个子数组。所以,自然的方式就是说int (*p)[numCols]
(意思是 p是一个指针,指向一个数组numCols
,整数)。在函数声明中,您有“快捷方式”p[]
,这意味着与(*p)
完全相同(但告诉读者,您将指针传递给数组的开头,而不仅仅是一个变量)
感谢您的解释.... – lakesh 2012-02-25 20:09:34
你正在做错的方式。您可以在指向数组的指针的帮助下传递二维数组,或者只传递一个数组或通过单指针。
#define numRows 3
#define numCols 7
void display(int (*p)[numcols],int numRows,int numCols)//First method//
void display(int *p,int numRows,int numCols) //Second Method//
void display(int numRows,int numCols,int p[][numCols]) //Third Method
{
printf("\n");
for (int i = 0; i < numRows;i++)
{
for (int j = 0; j < numCols;j++)
{
printf("%i\t",p[i][j]);
}
printf("\n");
}
}
int main() {
display(arr,numRows,numCols);
}
声明它只是
void display(int (*p)[numCols][numRows]);
这样你p
指针传达所有必要的信息,并可以提取其中的所有尺寸,而不重复numCols
和numRows
一遍又一遍。
void display(int (*p)[numCols][numRows])
{
size_t i, j;
printf("sizeof array=%zu\n", sizeof *p);
printf("sizeof array[]=%zu\n", sizeof **p);
printf("sizeof array[][]=%zu\n", sizeof ***p);
size_t dim_y = sizeof *p/sizeof **p;
printf("dim_y = %zu\n", dim_y);
size_t dim_x = sizeof **p/sizeof ***p;
printf("dim_x = %zu\n", dim_x);
for(i=0; i<dim_y; i++) {
puts("");
for(j=0; j<dim_x; j++)
printf(" %6d", (*p)[i][j]);
}
}
,如果你使用typedef(我不喜欢BTW)
typedef int matrix[5][6];
在这种情况下,这是特别有趣的尺寸是不可见的函数的签名,但功能依然会具有正确的尺寸值。
如下可以改变显示方法的签名:
void display(int (*p)[numCols])
这里,p
是一个指针到2D阵列的行。指针只需要知道数组中的列数。
其实说起来,指针需要知道每一行的大小。这对指针运算非常重要。所以当你增加指针时,指针必须指向下一行。
这里请注意,p
不是一个正常的整数指针。这是一个指向内存大小等于integer_size x columns
的整数指针。
主要你不需要改变任何东西。 display(arr)
就好了。
有几种,有时候也是这样做的。通过声明一个数组(参见method_c()
),使用指针(参见method_b()
)或使用指向数组数组的指针(参见method_a()
)。由于使用标准数组索引并不容易,所以使用单个指针稍微难以正确定位,因此我们使用指针算术。 method_a()
和method_c()
基本上是等价的,因为数组在编译期间非递归地衰减到指针。这是一个说明所有三种方法的小程序。我们首先在一个简单的for循环中初始化一个2x4
-array arr
并打印出来。它看起来像这样:
arr:
0 1 2 3
0 1 2 3
然后我们调用所有三种方法。 method_a()
增加1,method_b()
增加2和method_c()
增加3到所有元素。每次通话后,我们再次打印出阵列arr
。如果一个功能正常工作,您将很容易在输出中看到它。大小是任意的,可以通过两个宏ROW
和COL
进行调整。最后一个注释method_c()
自C99
起依赖于可变长度数组。
#include <stdio.h>
#include <stdlib.h>
#define ROW 2
#define COL 4
void method_a(int m, int n, int (*ptr_arr)[n]);
void method_b(int m, int n, int *ptr_arr);
void method_c(int m, int n, int arr[][n]);
int main(int argc, char *argv[]) {
int arr[ROW][COL];
int i;
int j;
for(i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
arr[i][j] = j;
}
}
printf("Original array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
method_a(ROW, COL, arr);
printf("method_a() array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
printf("method_b() array:\n");
method_b(ROW, COL, (int *)arr);
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
method_c(ROW, COL, arr);
printf("method_c() array:\n");
for (i = 0; i < ROW; i++) {
for(j = 0; j < COL; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n\n");
return EXIT_SUCCESS;
}
void method_a(int m, int n, int (*ptr_arr)[n])
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
ptr_arr[i][j] = j + 1;
}
}
}
void method_b(int m, int n, int *ptr_arr)
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
/* We need to use pointer arithmetic when indexing. */
*((ptr_arr + i * n) + j) = j + 2;
}
}
/* The whole function could have also been defined a bit different by taking
* the i index out of the pointer arithmetic. n alone will then provide our
* correct offset to the right. This may be a bit easier to understand. Our
* for-loop would then look like this:
* for (i = 0; i < m; i++)
* {
* for (j = 0; j < n; j++)
* {
* *((ptr_arr + n) + j) = j + 2;
* }
* ptr_arr++;
* }*/
}
void method_c(int m, int n, int arr[][n])
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
arr[i][j] = j + 3;
}
}
}
为什么我们在将数组传递给method_b()时需要做(int *)arr? – shane 2016-06-11 09:06:32
@ lord.garbage +1,注意method_c()的C99问题。 – 2017-10-07 18:02:20
对于上面的大多数答案,您需要知道至少不是。二维数组中的列。即使你通过了没有。函数本身中的列或声明否。全局列的一些编译器仍然可能会显示一些错误,并可能无法正常工作。 所以可以调用函数等
func((int **)a,r,c);
其中a是2-d阵列,和r和c是没有。行和列分别。 你能赶上在功能这些数据作为
void func(int **a,int r,int c);
,您可以通过使用指针,其中*((a+r*i)+j)
会给你的a[i][j]
值穿越它。
欢迎来到SO,在你的答案中使用代码标记更有用。 – 2015-06-27 14:43:43
不,你不能调用这样的函数。 – 2017-07-30 20:47:45
请参阅下面的答案。 – jupp0r 2012-02-25 18:23:24
可能重复[C - 传递一个2d数组作为函数参数?](http://stackoverflow.com/questions/6862813/c-passing-a-2d-array-as-a-function-argument) – 2012-02-25 21:03:15
小提示:对宏使用CAPS,这是常见的做法,可以让你的代码更清晰地告诉外部人员 – 2014-03-14 11:11:15