Cómo pasar una matriz multidimensional a una función en C y C++
#include<stdio.h>
void print(int *arr[], int s1, int s2) {
int i, j;
for(i = 0; i<s1; i++)
for(j = 0; j<s2; j++)
printf("%d, ", *((arr+i)+j));
}
int main() {
int a[4][4] = {{0}};
print(a,4,4);
}
Esto funciona en C, pero no en C++.
error:
cannot convert `int (*)[4]' to `int**' for argument `1' to
`void print(int**, int, int)'
¿Por qué no funciona en C++? ¿Qué cambio es necesario hacer?
Este código no funcionará ni en C ni en C++. Una matriz de tipo int[4][4]
no se puede convertir en un puntero de tipo int **
(que es lo que int *arr[]
significa en la declaración de parámetros). Si logró compilarlo en C, es simplemente porque probablemente ignoró una advertencia del compilador de C que tiene básicamente el mismo formato que el mensaje de error que recibió del compilador de C++. (A veces los compiladores de C emiten advertencias sobre lo que es esencialmente un error ).
Así que, de nuevo, no hagas afirmaciones que no sean ciertas. Este código no funciona en C. Para convertir una matriz 2D incorporada en un int **
puntero, puede utilizar una técnica como esta.
Convertir matrices multidimensionales en punteros en c++
(Vea la respuesta aceptada. El problema es exactamente el mismo).
EDITAR: El código parece funcionar en C porque otro error en el código de impresión enmascara los efectos del error en el paso de matrices. Para acceder correctamente a un elemento de una int **
pseudomatriz, debes usar una expresión *(*(arr + i) + j)
, o mejor una simple arr[i][j]
(que es lo mismo). Te perdiste el extra *
que hizo que imprimiera algo que no tiene absolutamente nada que ver con el contenido de tu matriz. Nuevamente, inicialice su matriz en main
otra cosa para ver que los resultados que está imprimiendo en C no tienen absolutamente nada que ver con el contenido previsto de la matriz.
Si cambia la printf
declaración como se muestra arriba, lo más probable es que su código falle debido al error de paso de matrices que describí inicialmente.
Una vez más: no se puede pasar una int[4][4]
matriz como una int **
pseudomatriz. Esto es lo que le dice C++ en el mensaje de error. Y estoy seguro de que esto es lo que le dijo su compilador de C, pero probablemente lo ignoró, ya que era "sólo una advertencia".
El problema es ese
int a[4][4];
en realidad se almacenará en una memoria físicamente continua. Entonces, para acceder a una parte arbitraria de su matriz 4x4, la función "imprimir" necesita conocer las dimensiones de la matriz. Por ejemplo, el siguiente pequeño fragmento de código accederá a la misma parte de la memoria de dos formas diferentes.
#include <iostream>
void print(int a[][4]) {
for (int i = 0; i <4; i++) {
for (int j = 0; j < 4; j++) {
//accessing as 4x4 array
std::cout << a[i][j] <<std::endl;
//accessing corresponding to the physical layout in memory
std::cout << *(*(a)+ i*4 + j) << std::endl;
}
}
}
int main() {
int a[4][4];
//populating the array with the corresponding indices from 0 to 15
int m = 0;
for (int i = 0; i<4; i++) {
for (int j= 0; j < 4; j++) {
a[i][j] = m;
m++;
}
}
print(a);
}
Entonces, el diseño de la memoria no cambia, pero sí la forma de acceder. Se puede visualizar como un tablero de ajedrez.
0 1 2 3
----------
0| 1 2 3 4
1| 5 6 7 8
2| 9 10 11 12
3|13 14 15 16
Pero la memoria física real se ve así.
0*4+0 0*4+1 0*4+2 0*4+3 1*4+0 1*4+1 1*4+2 1*4+3 2*4+1 etc.
-----------------------------------------------------
1 2 3 4 5 6 7 8 9 etc.
En C++ los datos de una matriz se almacenan fila por fila y la longitud de una fila (en este caso 4) siempre es necesaria para llegar al desplazamiento de memoria adecuado para la siguiente fila. Por lo tanto, el primer subíndice solo indica la cantidad de almacenamiento que se necesita cuando se declara la matriz, pero ya no es necesario para calcular el desplazamiento posterior.