Bennu Game Development

Foros en Español => Mesa de Ayuda => Topic started by: HaCkZJuaNN on February 20, 2009, 06:51:42 PM

Title: Pasar matriz como parámetro
Post by: HaCkZJuaNN on February 20, 2009, 06:51:42 PM
Si no me equivoco, para pasar una matriz como parámetro, hay que pasar un puntero al primer elemento y la longitud de la matriz, no?

Se pueden pasar matrices de más de una dimensión de este modo?

Es que tengo lo siguiente
[code language="bennu"]
function jmath_media_ponderada(jmath_numero numeros, int longitud, jmath_numero resultado) //numeros = jmath_numero[longitud][2], con numeros
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on February 20, 2009, 08:28:45 PM
no se los prototipos de las otras funciones... pero acostumbrate a usar &
Title: Re: Pasar matriz como parámetro
Post by: HaCkZJuaNN on February 20, 2009, 08:33:51 PM
Con todos los punteros y follones que manejo, el código se haría ilegible, pero ya lo hablé contigo y entendí que mientras tenga claro qué son punteros y qué no lo son no hay problema...

Con respecto al problema en sí, dónde está el fallo?
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on February 20, 2009, 08:44:41 PM
es que no siempre por mas que sea una matriz si pasas el elemento se pasa como puntero

si yo tengo esto

int a[10];

y paso

a o &a

entonces paso el puntero

ahora si paso

a[0] o a[1]

entonces paso su valor...

pero si paso

&a[0] o &a[1]

entonces si paso el puntero
Title: Re: Pasar matriz como parámetro
Post by: HaCkZJuaNN on February 20, 2009, 09:04:11 PM
Ya, pero es que mi matriz no es de ints, sino de jmath_numero, por lo que cada elemento se pasa como puntero también. No obstante, voy a probar lo que dices y ahora te digo.

EDIT: No funciona. Por cierto, el error que me da es de compilación, no hay ninguna llamada a esa función todavía, sólo estaba probando si compilaba.

[code language="bennu"]function jmath_media_ponderada(jmath_numero pointer numeros, int longitud, jmath_numero resultado) //numeros = jmath_numero[longitud][2], con numeros
Title: Re: Pasar matriz como parámetro
Post by: laghengar on February 20, 2009, 09:40:54 PM
creo que estás fallando en el "*numeros", al ser "numeros" ya un puntero por declararle como "pointer", solo tendrías que poner "numeros".
Title: Re: Pasar matriz como parámetro
Post by: HaCkZJuaNN on February 20, 2009, 10:05:36 PM
También lo he probado, y falla en el 1, la primera dimensión la tolera, pero la segunda parece que no...
Title: Re: Pasar matriz como parámetro
Post by: HaCkZJuaNN on February 20, 2009, 10:46:47 PM
Por las pruebas que he hecho, estoy casi seguro de que el problema es que la matriz tiene 2 dimensiones. Se trata de un bug, de una limitación lógica, o para utilizar matrices de varias dimensiones hay que hacerlo de otra manera???
Title: Re: Pasar matriz como parámetro
Post by: HaCkZJuaNN on February 20, 2009, 11:00:28 PM
Otra cosa más, el for tenía una cosa al revés xD pero eso no era lo que causaba el error. Al final lo estoy haciendo separando la matriz en varias matrices unidimensionales, porque en este caso no importa, pero me gustaría saber si se puede hacer con matrices de más de una dimensión para otros posibles casos. De nuevo gracias.
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on February 20, 2009, 11:29:39 PM
1) la linea despues del for te falta el ";" ?
2) claro, esta mal como lo estas usando...
"numeros" =  "jmath_numero pointer"

al hacer "numeros[numero_actual]" o "(*numeros)" ya consumiste el pointer... por ende no podes luego hacer un "[1] y mucho menos un "[numero_actual][1]"...

no va, esta mal usado...

EDIT: perdon pero antes no habia prestado mucha atencion al codigo, solo al texto... seria bueno tambien que pongas la declaracion del tipo, aunque en este caso no hace al problema.
Title: Re: Pasar matriz como parámetro
Post by: HaCkZJuaNN on February 20, 2009, 11:48:06 PM
Bueno, entonces cómo tengo que usarlo? no he puesto aquí todas las combinaciones que he probado, y parece que lo más que logra es entender la primera dimensión, pero la segunda no.

Se puede o no se puede utilizar una matriz de 2 dimensiones como parámetro??
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on February 20, 2009, 11:59:53 PM
si, claro que si...

suponiendo que queremos direccionar por [ a ][ b ] es...

numeros[(a)*ancho_del_array+(b)]
Title: Re: Pasar matriz como parámetro
Post by: HaCkZJuaNN on February 21, 2009, 12:31:05 PM
:O, ancho es la longitud de la segunda dimensión según lo entiendo no?

Nunca se me hubiera ocurrido. Para tres dimensiones, si queremos ir a [code language="bennu"]
[a][c], siendo [a] largo, ancho y [c] alto(por ejemplo) habría que hacer lo siguiente, no?

matriz[(a)*ancho*alto+(b)*alto+(c)]

[/code]
no??

Perdón pero es que quiero tener esto claro :) y gracias de nuevo.
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on February 21, 2009, 02:00:59 PM
toda matriz es un vector...

de otra forma...

[dimension1] [dimension2] [dimension3]

matriz[(dimension1)*size_dimension2*size_dimension3+(dimension2)*size_dimension1+dimension1]
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on February 21, 2009, 02:01:49 PM
pero igual no es aconsejable trabajar de esta forma... las operaciones significarian un consumo bastante importante.
Title: Re: Pasar matriz como parámetro
Post by: HaCkZJuaNN on February 21, 2009, 03:37:30 PM
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 :)
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on February 21, 2009, 03:41:28 PM
de nada... saludos...
Title: Re: Pasar matriz como parámetro
Post by: Windgate on April 30, 2009, 08:56:15 PM
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 (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.
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on April 30, 2009, 11:11:57 PM
Perdon, pero no es muy diferente a C, en C tambien se pueden acceder a los arrays de esta forma
Title: Re: Pasar matriz como parámetro
Post by: Windgate on May 01, 2009, 08:32:13 AM
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!
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on May 01, 2009, 01:38:18 PM
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...
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on May 01, 2009, 01:48:43 PM
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;
}
Title: Re: Pasar matriz como parámetro
Post by: Windgate on May 02, 2009, 09:39:47 AM
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.
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on May 02, 2009, 01:36:10 PM
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.
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on May 02, 2009, 01:37:21 PM
Evidentemente con [1][1] no me pase de ningun rango.
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on May 02, 2009, 02:38:07 PM
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...
Title: Re: Pasar matriz como parámetro
Post by: SplinterGU on May 02, 2009, 02:54:07 PM
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.
Title: Re: Pasar matriz como parámetro
Post by: Windgate on August 26, 2009, 02:49:54 PM
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 (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 :'(
Title: Re: Pasar matriz como parámetro
Post by: HaCkZJuaNN on August 26, 2009, 03:04:20 PM
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].
Title: Re: Pasar matriz como parámetro
Post by: splinter_work on August 26, 2009, 03:12:17 PM
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...

Title: Re: Pasar matriz como parámetro
Post by: Windgate on August 26, 2009, 04:27:56 PM
De hecho por ahora lo he solucionado así, al declarar la matriz la declaro de [3][3] para tener matrices que van desde [ 0 ] [ 0 ] hasta [ 3 ] [ 3 ] (Matrices de 4x4)

La costumbre de C y de todos los lenguajes con los que había trabajado hasta ahora me había vuelto un poco locuelom pero ya está.

Y además ahora me doy cuenta de que siempre había declarado matrices (Y vectores...) de 1 dimensión más de lo que necesitaba sin saberlo.

Menos mal que el mal no ha sido mayor y no me ha costado demasiado arreglar el código, ya estaba pensando en algún posible bug de las DLL :-\