将二维数组传递给函数的正确方法
我有一个二维数组,我将它传递给一个函数来执行某些操作。 我想知道正确的做法…
#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*'
这是将二维数组传递给函数的正确方法吗? 如果不是,那么正确的方法是什么?
你应该像这样声明你的函数:
void display(int p[][numCols])
这C常见问题彻底解释了原因。 它的要点是数组一次衰变成指针,不会发生recursion。 数组的数组衰减成指向数组的指针,而不是指向指针的指针。
如果(就像你的情况一样),你知道编译时数组的维数,你可以编写void display(int p[][numCols])
。
一些解释:你可能知道,当你传递一个数组到一个函数,你实际上传递了一个指针到第一个成员。 在C语言中,二维数组只是一个数组的数组。 因此,您应该将函数传递给2D数组中的第一个子数组。 所以,自然的方法就是说int (*p)[numCols]
(这意味着p是一个指针,指向一个numCols
int数组 )。 在函数声明中,你有“快捷方式” p[]
,这意味着完全一样的东西像(*p)
(但是告诉读者,你传递一个指针到数组的开始,而不是一个variables)
你做错了。 您可以通过指向数组的指针传递二维数组,或者只传递一个数组或通过单个指针。
#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); }
有几种,有时候也是这样做的。 通过使用指针(cf. method_b()
)或使用指向数组数组的指针(参考method_b()
)来声明数组(参见method_c()
method_a()
)。 method_b()
,使用单个指针,稍微难以正确使用,因为使用标准数组索引是不容易的,因此我们使用指针algorithm。 method_a()
和method_c()
基本上是等价的,因为数组在编译期间非recursion地衰减到指针。 这是一个说明所有三种方法的小程序。 我们首先在一个简单的for循环中初始化一个2x4
-array arr
并打印它。 它看起来像这样:
arr: 0 1 2 3 0 1 2 3
之后我们调用所有三种方法。 method_a()
添加1, method_b()
添加2, method_c()
将3添加到所有元素。 每次调用后,我们再次打印数组arr
。 如果一个function正常工作,你会很容易看到它的输出。 大小是任意的,可以通过两个macrosROW
和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; } } }
简单地声明
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]); } }
这是特别有趣的,如果你使用typedefs(我不喜欢btw)
typedef int matrix[5][6];
在这种情况下,尺寸在function的签名中是不可见的,但function仍然具有正确的尺寸值。
您可以更改显示方法的签名,如下所示:
void display(int (*p)[numCols])
这里, p
是一个指向2D数组的行的指针。 指针只需要知道数组中的列数。
实际上,指针需要知道每一行的大小。 这对指针运算非常重要。 所以当你增加指针时,指针必须指向下一行。
这里请注意, p
不是一个普通的整数指针。 这是一个整数指针的内存大小等于integer_size x columns
。
主要你不需要改变任何东西。 display(arr)
就好了。
对于上面的大多数答案,你需要知道至less不是。 二维数组中的列。 即使你通过了没有。 在函数本身中的列或声明不。 全局的列,一些编译器仍然可能会显示一些错误,它可能无法正常工作。 所以你可以调用这个函数
func((int **)a,r,c);
其中a是二维数组,而r和c是否定的。 行和列分别。 你可以在函数中捕获这些数据
void func(int **a,int r,int c);
你可以通过使用指针来遍历它,其中*((a+r*i)+j)
会给你a[i][j]
。