Forma correcta de pasar una matriz bidimensional a una función

Tengo una matriz bidimensional y la estoy pasando a una función para llevar a cabo ciertas operaciones. Me gustaría saber la forma correcta de hacerlo …

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

Aparece un mensaje de error:

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

¿Es esta la forma correcta de pasar una matriz bidimensional a una función? Si no, ¿cuál es la forma correcta?

Deberías declarar tu función así:

 void display(int p[][numCols]) 

Estas preguntas frecuentes de C explican a fondo por qué. La esencia de esto es que las matrices se descomponen en punteros una vez , no ocurre recursivamente. Una matriz de matrices se descompone en un puntero a una matriz, no en un puntero a un puntero.

Si (como en su caso) conoce las dimensiones de la matriz en tiempo de comstackción, puede escribir la void display(int p[][numCols]) .

Alguna explicación: probablemente sepa que cuando pasa una matriz a una función, en realidad pasa un puntero al primer miembro. En el lenguaje C, la matriz 2D es solo una matriz de matrices. Por eso, debe pasar la función un puntero a la primera sub-matriz en la matriz 2D. Por lo tanto, la forma natural es decir int (*p)[numCols] (que significa que p es un puntero, a una matriz de enteros numCols ). En statement de función, tiene el “acceso directo” p[] , que significa exactamente lo mismo que (*p) (Pero le dice al lector, que pasa un puntero al principio de la matriz y no a una sola variable)

Lo estás haciendo de manera equivocada. Puede pasar una matriz de 2 d con la ayuda de un puntero a una matriz o simplemente pasar una matriz o puntero único.

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

Hay varias formas, a veces equivalentes, de hacer esto. Al declarar una matriz (compárese con method_c() ), usando un puntero ( method_b() ) o usando un puntero a una matriz de una matriz ( method_a() ). method_b() , usando un único puntero, es un poco más difícil de corregir ya que no es fácil usar la indexación de matriz estándar y, por lo tanto, usamos la aritmética de puntero. method_a() y method_c() son básicamente equivalentes, ya que las matrices decaen de forma no recursiva en los punteros durante la comstackción. Aquí hay un pequeño progtwig que ilustra los tres métodos. Primero inicializamos un array de 2x4 en un bucle for simple e imprimimos. Se verá así:

 arr: 0 1 2 3 0 1 2 3 

Luego llamamos a los tres métodos. method_a() agrega 1, method_b() agrega 2 y method_c() agrega 3 a todos los elementos. Después de cada llamada, imprimimos la matriz arr nuevamente. Si una función funcionó correctamente, la verá fácilmente en la salida. El tamaño es arbitrario y se puede regular mediante las dos macros ROW y COL . Una última nota, method_c() basa en una matriz de longitud variable presente desde C99 .

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

Declararlo simplemente

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

De esta forma, su puntero p transmite toda la información necesaria y puede extraer todas las dimensiones sin repetir numCols y numRows una y otra vez.

 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 

Esto es particularmente interesante si usas typedefs (que no me gusta por cierto)

  typedef int matrix[5][6]; 

En ese caso, las dimensiones no son visibles en la firma de la función, pero la función aún tendrá los valores correctos para las dimensiones.

Puede cambiar la firma del método de visualización de la siguiente manera:

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

Aquí, p es un puntero a la fila de una matriz 2D. El puntero solo necesita saber el número de columnas en la matriz.

En realidad, el puntero necesita saber el tamaño de cada fila. Esto es muy importante para la aritmética del puntero. De modo que cuando incremente el puntero, el puntero debe apuntar a la siguiente fila.

Tenga en cuenta que p no es un puntero entero normal. Es un puntero entero al tamaño de la memoria igual a integer_size x columns .

En main no necesitas cambiar nada. display(arr) está bien.