Pasar matriz como parámetro

Started by HaCkZJuaNN, February 20, 2009, 06:51:42 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

HaCkZJuaNN

Pero es el único modo de pasar matrices como parámetros... De todas formas tendré en cuenta que es poco aconsejable.

Aún así, no creo que utilice muchas funciones a las que les pases matrices como parámetros, y de todas formas, lo que estoy haciendo ya pierde performance por casi todos los laos, pero es la única manera de hacerlo como yo pretendo, así que estoy haciendo todo lo que puedo por hacerlo lo más rápido posible evitando operaciones, pero a veces es inevitable...

Así que ok, entendido, gracias y un saludo :)

SplinterGU

Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Windgate

Tengo algo que aportar al tema.

Confirmo que las matrices se pasan con un único pointer al primer elemento. Para acceder a cierta fila, columna, etc hay que realizar las operaciones que dijo SplinterGU. Esto lo hace MUY diferente de C. Es una lástima porque el método para pasar matrices de C era muy intuitivo y no requería operar con tamaños de fila/columna para acceder a elementos.

Aporto un sencillo programa Bennu en el que uso un producto de matrices y vectores y paso las matrices como parámetro:

http://www.mediafire.com/?dtnwzlymjwq

La finalidad de este programa es implementar un visor de modelos 3D en un formato muy sencillo usando primitivas 2D. Pienso usarlo como proyecto para una de mis últimas asignaturas de ingeniería informática. ¡¡¡Sí, con Bennu!!! xDDD

El programa en cuestión es sencillo pero implementa algunas de las utilidades comentadas en los últimos topics, como centrado de ventana y cambio de ventana a pantalla completa con Alt+Enter. Todo separado en distintos PRG que espero puedan servir de ayuda para ser reutilizados en vuestros proyectos.
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

SplinterGU

Perdon, pero no es muy diferente a C, en C tambien se pueden acceder a los arrays de esta forma
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Windgate

Sí, pero la diferencia es que en C para pasar una matriz (Vector de vectores) puedes pasar un puntero a un puntero al dato:

Para declarar la función:
void funcion(int **parametro)
Y dado el dato:
int m[16][8];
Puedes invocar la función así:
funcion(m);
La función puede acceder a los datos de la matriz sin hacer cálculos:
parametro[0][0], parametro[2][4]

La diferencia en Bennu es que la declaración de la función lleva un único puntero al dato:

Para declarar la función:
function funcion(int pointer parametro)
Invocas la función así:
funcion(&m[0][0]);
La función accede a los elementos calculando:
parametro[0*16+0], parametro[2*16+4]

Si muy diferente no es, pero C permite hacerlo de forma más "limpia", sobre todo cuando se trata de una matriz de muchas dimensiones. Por ahora en la "vida real" lo máximo que he tenido ha sido una matriz de cuatro dimensiones, y escribir el código se hace más pesado.

Si se pudiese declarar una función auxiliar encargada de resolver la operación como private... Son simples sugerencias. La cosa funcionar funciona!

Buen hilo!
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

SplinterGU

No, no es asi, en C si vos pasas un ** dentro de la funcion no sabes la dimension real del array que pasas...

En bennu tambien podes pasar **...

Explicandolo de otra forma...

vos tenes

int m[16][8];

y

void funcion(int ** parametro)

pasas funcion(m)...

dentro de "funcion" no podes usar "parametro", haciendo parametro[2][4], ya que para poder hacer esto, "funcion" debe conocer las dimensiones de parametro, pero el solo sabe que es ** (puntero puntero), pero no sabe puntero puntero de que dimensiones... podria pasarle tranquilamente un m[16][8] como un g[130][1000], a "funcion" le da lo mismo...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

#21
ejemplo:


#include < stdio.h>


int function(int ** param)
{
    printf ("%d\n", param[1][1]);

}

int main(int argc, char * argv[])
{
    int a[3][3] = {1,2,3,4,5,6,7,8,9};
    int b[4][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

    function(a);
    function(b);
//    function(&a[0][0]);

    return 0;

}


Da un hermoso violacion de segmento...

Lo raro es que el compilador C permita compilar la linea "printf ("%d\n", param[1][1]);" deberia dar un error al no conocer las dimensiones del elemento

Diferente es, si hacemos esto (tal cual digo que hay que hacer en Bennu):


#include < stdio.h>

int function(int ** param, int h, int w)
{
    printf ("%d\n", param[1*h + 1]);
}

int main(int argc, char * argv[])
{
    int a[3][3] = {1,2,3,4,5,6,7,8,9};
    int b[4][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

    printf ("main a[1][1]=%d\n", a[1][1]);
    printf ("main b[1][1]=%d\n", b[1][1]);

    printf ("function a[1][1]=");
    function(a,3,3);
    printf ("function b[1][1]=");
    function(b,4,4);

    return 0;
}
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Windgate

Mmmmh... Juraría que con C en la universidad (El C más antiguo con las librerías más antiguas que podamos imaginar los mortales) sí que podía trabajar como te digo, con ** para definir el parámetro y accediendo a los elementos con [][]. Según se nos dijo, C tiene un nivel entre alto y bajo (Entre Java y ensamblador), y accede zonas de memoria sin comprobar violaciones de segmento y cosas así.

La matriz es un puntero, y con el primer [] se accede a otro puntero, y con el segundo [] aplicado a ese puntero se accede al dato en cuestión. Si te pasas con los rangos puede que llegues a un espacio de memoria que esté fuera de la matriz, pero siempre que forme parte del programa podrás accederlo sin problemas. Eso es lo que tenía en el coco hasta ahora...

En cualquier caso te tomo la palabra porque hace ya unos años de eso y veo que tú lo tienes más fresco que yo. Accederé a los elementos haciendo las operaciones pertinentes.
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

SplinterGU

es simple logica...

C no hace las cosas por arte de magia.
un array sigue siendo una serie de valores en areas de memoria consecutivas (lineal), (por ejemplo, la pantalla es un array) los array se puede acceder tanto linealmente como por medio de sus dimensiones.

Para acceder a elementos de un array "C" hace uso de la formula que yo mencione... si la funcion no conoce las dimensiones no puede usar la formula para acceder a la memoria...

Es simple logica.

Pensalo, escribilo en papel, y lo vas a entender.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

Evidentemente con [1][1] no me pase de ningun rango.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

#25
Ahora sin embargo en C hacemos esto...


#include <stdio.h>

int function(int param[3][3], int h, int w)
{
    printf ("%d\n", param[1][1]);
}

int main(int argc, char * argv[])
{
    int a[3][3] = {1,2,3,4,5,6,7,8,9};
    int b[4][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

    printf ("main a[1][1]=%d\n", a[1][1]);
    printf ("main b[1][1]=%d\n", b[1][1]);

    printf ("function a[1][1]=");
    function(a,3,3);
    printf ("function b[1][1]=");
    function(b,4,4);

    return 0;
}


No se produce la violacion de segmento, ya que funcion conoce las dimensiones, pero si prestas atencion, tanto "a" como "b" se acceden como si fuesen de 3x3... y con esto se demuestra lo que digo que un array es una serie de valores dispuestos en forma lineal en un area de memoria.

Un array de [ a ][ b ] = a un vector de [a*b]

En bennu por el momento no es posible declarar ese tipo de parametros a una funcion...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

SplinterGU

Otra opcion (ideal) pero que solo funciona en gcc (no funciona en otros compiladores, por lo menos hasta donde comprobe, y tampoco en bennu):


#include <stdio.h>

int function(int h, int w, int param[h][w])
{
    printf ("%d\n", param[1][1]);
}

int main(int argc, char * argv[])
{
    int a[3][3] = {1,2,3,4,5,6,7,8,9};
    int b[4][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

    printf ("main a[1][1]=%d\n", a[1][1]);
    printf ("main b[1][1]=%d\n", b[1][1]);

    printf ("function a[1][1]=");
    function(3,3,a);
    printf ("function b[1][1]=");
    function(4,4,b);

    return 0;
}


Obviamente esto el gcc lo hace en runtime, cosa que bennu no puede hacer ya que todo este tipo de cosas las hace en momento de compilacion.
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

Windgate

Vuelvo a reflotar el tema ya que he tenido un error raro con el paso de matrices como parámetro, os dejo la descarga del programa, es brevísima:

DESCARGAR: http://www.mediafire.com/?gnzn02zzdjz

El caso es que defino una: int matriz[4][4]

Y yo tenía entendido que podría acceder desde matriz[0][0] hasta matriz[3][3] pero resulta que me permite introducir datos hasta en matriz[4][4]  ???  ???  ???

El problema de ésto es que al pasar la matriz como parámetro, es como si fuese un vector[5*5] y no me funciona el muestreo de datos haciendo:

matriz [ fila * dimension + columna ];

Si no que tengo que hacerlo así para que funcione correctamente:

matriz [ fila * (dimension+1) + columna ];

O bien:

matriz [ fila * dimension + columna + columna ];

¿Será algún problema de mis versiones de las DLL?

Llevo unas horas haciendo pruebas y el problema es ese, que al crear arrays (O matrices) reservan 1 posición más de lo que deberían.

HELP :'(
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

HaCkZJuaNN

Creo que lo que pasa es que en bennu y fénix la declaración de matrices no funciona como en otros lenguajes, y si tu declaras matriz[4][4], va a crear una matriz de 5x5 que va desde matriz[0][0] hasta matriz[4][4], al contrario de lo que tú esperas, y eso crea todos esos problemas que tú tienes. Prueba a declararla como matriz[3][3] y hacer todo igual que como lo estabas haciendo, y deberia funcionar como una matriz de 3x3, claro que para utilizar lo otro tendrías que hacer matriz[fila*(dimension+1)+columna].

splinter_work

varios lenguajes funcionan asi... C no lo hace y algun otro...

dimensionarlo [3][3] funcionaria como una matris de 4x4, en las definiciones de las dimensiones se indica hasta que valor contendra esa dimension, no cuantos valores tiene...