Cómo pasar una matriz multidimensional a una función en C y C++

Resuelto Moeb asked hace 14 años • 0 respuestas
#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?

Moeb avatar May 13 '10 23:05 Moeb
Aceptado

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 mainotra 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 printfdeclaració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".

AnT stands with Russia avatar May 13 '2010 16:05 AnT stands with Russia

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.

Lucas avatar May 13 '2010 18:05 Lucas