我有一个二维数组,我将它传递给一个函数来执行某些操作.我想知道这样做的正确方法......
#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);
}
Run Code Online (Sandbox Code Playgroud)
我收到一条错误消息:
'display': cannot convert parameter1 from 'int' to 'int*'
Run Code Online (Sandbox Code Playgroud)
这是将二维数组传递给函数的正确方法吗?如果没有,那么正确的方法是什么?
cni*_*tar 69
你应该声明你的函数:
void display(int p[][numCols])
Run Code Online (Sandbox Code Playgroud)
这个C FAQ彻底解释了原因.它的要点是数组一旦衰减成指针,它不会递归地发生.数组数组衰变为指向数组的指针,而不是指向指针的指针.
asa*_*elr 13
如果(在你的情况下),你知道编译时数组的维度,你可以写void display(int p[][numCols]).
一些解释:您可能知道,当您将数组传递给函数时,实际上是将指针传递给第一个成员.在C语言中,2D数组只是一个数组数组.因此,您应该将函数指向2D数组中的第一个子数组.所以,自然的方式就是说int (*p)[numCols](这意味着p是一个指针,指向一组numColsint).在函数声明中,你有"快捷方式" p[],这意味着完全相同的东西(*p)(但告诉读者,你将指针传递给数组的开头,而不只是一个变量)
你做错了.您可以在指向数组的指针的帮助下传递二维数组,或者只是传递数组或通过单指针传递.
#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);
}
Run Code Online (Sandbox Code Playgroud)
有几种,有时是等效的方法.通过method_c()使用指针(参见method_b())或使用指向数组数组的指针(参见)来声明一个数组(参见method_a()).method_b()由于使用标准数组索引并不容易,因此使用单个指针稍微难以正确使用,因此我们使用指针算法.method_a()并且method_c()基本上是等效的,因为数组在编译期间非递归地衰减到指针.这是一个小程序,说明了所有三种方法.我们首先在一个简单的for循环中初始化一个2x4-array arr并打印它.它看起来像这样:
arr:
0 1 2 3
0 1 2 3
Run Code Online (Sandbox Code Playgroud)
然后我们调用所有三种方法.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;
}
}
}
Run Code Online (Sandbox Code Playgroud)