The correct way to pass a 2-dimensional array to a function

I have a two-dimensional array, and I pass it to a function to perform certain operations. I would like to know the right way to do this ...

#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); } 

The error message appears:

 'display': cannot convert parameter1 from 'int' to 'int*' 

Is this the correct way to pass a two-dimensional array into a function? If not, what is the right way?

+50
c
Feb 25 '12 at 18:20
source share
7 answers

You must declare your function as follows:

 void display(int p[][numCols]) 

This C FAQ fully explains why. Its essence is that arrays decompose into pointers once , this does not happen recursively. An array of arrays splits into a pointer to an array, not a pointer to a pointer.

+69
Feb 25 '12 at 18:23
source share
โ€” -

If (as in your case), you know the size of the array at compile time, you can only write void display(int p[][numCols]) .

Some explanation: you probably know that when you pass an array to a function, you are actually passing a pointer to the first member. In C, a 2D array is an array of arrays. Because of this, you must pass a function to a pointer to the first sub-array in a 2D array. So the natural way is int (*p)[numCols] (this means that p is a pointer to an array from numCols ints ). In the function declaration, you have "shortcut" p[] , which means exactly the same thing as (*p) (but tells the reader that you are passing a pointer to the beginning of the array, not just one variable)

+13
Feb 25 '12 at 18:23
source share

You are doing wrong. You can pass the 2nd array using a pointer to an array or just pass an array or through a single pointer.

 #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); } 
+5
Jun 10 '13 at 8:04 on
source share

There are several, sometimes equivalent, ways to do this. Declaring an array (cf. method_c() ), using a pointer (cf. method_b() ) or using a pointer to an array of array (cf. method_a() ). method_b() , using a single pointer, is a little more difficult to get right, because it is not easy to use standard array indexing and therefore we use pointer arithmetic. method_a() and method_c() are basically equivalent, since arrays do not recursively break into pointers at compile time. Here is a small program illustrating all three methods. First, we initialize the 2x4 -array arr in a simple loop and print it. It will look like this:

 arr: 0 1 2 3 0 1 2 3 

Then we call all three methods. method_a() adds 1, method_b() adds 2 and method_c() adds 3 to all elements. After each call, we again display the arr array. If the function works correctly, you can easily see it at the output. The size is arbitrary and can be adjusted using the two macros ROW and COL . The last note of method_c() uses the variable-length array present since 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; } } } 
+4
May 10 '15 at 16:34
source share

Declare it simply

 void display(int (*p)[numCols][numRows]); 

Thus, your pointer p passes all the necessary information, and you can extract all dimensions from it without repeating numCols and numRows again and again.

 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]); } } 

This is especially interesting if you use typedefs (which I don't like btw)

  typedef int matrix[5][6]; 

In this case, the dimensions are not visible in the function signature, but the function will still have the correct values โ€‹โ€‹for the dimensions.

0
Jun 10 '13 at 13:20
source share

You can change the signature of the display method as follows:

 void display(int (*p)[numCols]) 

Here p is a pointer to a string of a two-dimensional array. The pointer only needs to know the number of columns in the array.

In fact, the pointer must know the size of each row. This is very important for pointer arithmetic. So that when pointing to a pointer, the pointer points to the next line.

Note that p not a normal integer pointer. This is an integer pointer to a memory size equal to integer_size x columns .

Basically you do not need to change anything. display(arr) just fine.

0
May 08 '15 at 10:53
source share

For most of the answers above, you need to know, at least not. columns in a 2-dimensional array. And even if you pass no. columns in the function itself or declare no. columns globally, some compilers may show some errors, and this may not work. So you can call a function like

 func((int **)a,r,c); 

where a is a 2-dimensional array, but r and c are not. rows and columns respectively. You can catch this data in a function like

 void func(int **a,int r,int c); 

And you can cross it with pointers, where *((a+r*i)+j) will give you the value a[i][j] .

-one
Jun 27 '15 at 14:22
source share



All Articles