[C con Clase] Problema conceptual al pasar por referencia array de 2 dimensiones en C

Horacio Peñafiel horacio.penafiel en donweb.com
Lun Jun 15 16:36:07 CEST 2015


Diego, mirá estos posts en StackOverflow:

*http://stackoverflow.com/questions/2003745/pointer-address-in-a-c-multidimensional-array*
*http://stackoverflow.com/questions/2828648/how-to-pass-a-multidimensional-array-to-a-function-in-c-and-c*

Por ahí a largo plazo si lo que necesitás es clarificar el código de 
llamada a la función, podrías armarte una mini-biblioteca de funciones 
que encapsulen el acceso a las matrices, y encapsular la complejidad de 
punteros ...

Saludos!

Ing. Horacio Peñafiel


El 11/06/2015 a las 03:30 p.m., Diego escribió:
> Hola Horacio, muchas gracias por la ayuda.
>
> Esos dos artículos tratan sobre arrayes unidimensionales, se entienden 
> y no radica ahí el problema.
>
> Mi problema / duda surge al intentar interpretar la forma correcta en 
> que debería pasarle un array bidimensional a una función, ya que el 
> compilador lo interpreta como un puntero doble (si en el prototipo 
> declaro que es un puntero simple, da Warning) pero si lo utilizo como 
> puntero doble da error, ya que no es un puntero a punteros sinó que 
> apunta a direcciones contiguas de memoria con el contenido de los 
> datos en forma ordenada, según la posición mas el índice. Es decir, a 
> mi entender, el compilador entiende que es un puntero doble pero lo 
> trata como uno simple y ahí aparecen mis confusiones.
>
> La solución especificando que tipo entradas exige y haciendo casting 
> de variables, ya sea antes o después de la función, pero estoy seguro 
> que estoy haciendo algo mal y que hay una explicación y una solución 
> mas elegante y correcta.
>
> Dado:
> float numeros[5][5];
>
> Con el prototipo:
> Pasar(float **numeros);
>
> Si adentro de la función lo utilizo como un puntero a float, da 
> warning. Para subsanarlo utilizo un cast a (float *)
> Si adentro de la función lo utilizo como puntero doble da error (ya 
> que no es un puntero a punteros)
>
> Si el prototipo es:
> Pasar(float *numeros);
> Da warning, el compilador entiende que numeros[][] es un puntero a 
> puntero, puedo castearlo con (float *).
>
> El problema es que mediante las técnicas que se me ocurren, siempre 
> tengo que castearlo para evitar errores y eso me hace pensar que estoy 
> haciendo las cosas mal, o que tengo un error conceptual. Es así?
>
> Saludos y gracias
> Diego
>
>
>
> El 11 de junio de 2015, 11:20, Horacio Peñafiel 
> <horacio.penafiel en donweb.com <mailto:horacio.penafiel en donweb.com>> 
> escribió:
>
>     Diego, buscando en la web, encontré estos dos sitios, por ahí
>     ayude a clarificar el tema:
>
>     *http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c**
>     **http://www.le.ac.uk/users/rjm1/cotter/page_59.htm**
>     *
>     Saludos!
>
>     ing. Horacio Peñafiel
>
>
>
>     El 11/06/2015 a las 11:08 a.m., Diego escribió:
>>     Comento y pregunto, mas que nada, por una cuestión académica.
>>
>>     Lo que me llevó a pensar que se trataba de un doble puntero es que si
>>     no paso como parámetro un float * da warning ya que entiende que
>>     referencia[5][5] es un doble puntero y no uno simple (fácilmente se
>>     subsana con un cast), a alguien se le ocurre porque asume que el
>>     compilador entiende que un float [5][5] debe ser direccionado como
>>     puntero doble según los warnings, pero es es tratado como puntero
>>     simple?
>>
>>     Saludos!
>>     Diego
>>
>>     El día 10 de junio de 2015, 17:48, Diego<diegogeid en gmail.com>  <mailto:diegogeid en gmail.com>  escribió:
>>>     Hola, gracias a ambos. Ambos tienen razón en decir que los arrays
>>>     bidimensionales no se tratan de igual forma que punteros dobles, no
>>>     los organiza de esa forma.
>>>
>>>     El error surgió porque, tal como un array se puede direccionar como
>>>     una variable a puntero debido a su organización de memoria, asumí que
>>>     un array bidimensional se puede interpretar como un array de punteros
>>>     a punteros, NO SE ORGANIZA ASÍ EN MEMORIA, en realidad es un array de
>>>     [MxN], de esa forma, Horacio, la solución que brindas solo sirve para
>>>     los elementos de la primera fila. El parámetro a pasar, como bien
>>>     indicas Horacio es un puntero a float, y para utilizar el elemento M,
>>>     N debería usar referencia[M*5+N], creo que es la solución que indicás
>>>     Felipe, o definir el pasaje de referencia como referencia[5][5] en el
>>>     prototipo de la función, o en un tercer caso, definir como puntero a
>>>     puntero correctamente, inicializar y ahí direccionar como hice adentro
>>>     de la función. Ese caso sería mas eficiente si voy a utilizar varias
>>>     veces los índices.
>>>
>>>     Finalmente, Felipe, entiendo que puede haber diferencias en el tamaño
>>>     de datos, pero no creo que influya el tamaño de datos en el problema,
>>>     siempre que se asigne correctamente como puntero a float, mas allá de
>>>     la arquitectura, agradezco si es una aclaración, si es una confusión,
>>>     no dudes en plantearla.
>>>
>>>     Saludos y gracias a ambos!
>>>     Diego
>>>
>>>
>>>
>>>
>>>
>>>     El día 10 de junio de 2015, 17:03, Felipe Valencia<anfevp en gmail.com>  <mailto:anfevp en gmail.com>  escribió:
>>>>     Hola,
>>>>
>>>>     Esencialmente existe una diferencia entre como se organizan los dople
>>>>     punteros y las matrices de dos dimensiones. Las marices de dos dimensiones
>>>>     se organizan consecutivamente y los dobles punteros estan esparcidos en
>>>>     memoria.
>>>>
>>>>     Mira este enlace
>>>>     http://stackoverflow.com/questions/4470950/why-cant-we-use-double-pointer-to-represent-two-dimensional-arrays
>>>>     (Ingles)
>>>>
>>>>     De hecho en la posicion test[1] esta el valor de la siguiente linea, seria
>>>>     un 6 si continuaras con la inicializacion, y en la posicion referencia[1]
>>>>     sera leida como la direccion de la siguiente linea.
>>>>
>>>>     Ademads en PC de  64 bits los punteros son de 64 bits y los float son de 32
>>>>     bits. Agrega la linea printf("Size %d %d \n",sizeof(float*),sizeof(float));
>>>>
>>>>     Yo usualmente en estos casos uso matrices de una dimension en vez de dos
>>>>     dimensiones, y calculo los indices, o solo uso punteros reservando memoria
>>>>     con malloc o new.
>>>>
>>>>     Ademas uso como IDE eclipse el cual trae un debuggeador donde puedes vez los
>>>>     valores en memoria, supongo que Code::Blocks tambien debe mostrar memoria
>>>>
>>>>
>>>>     Chao!!
>>>>
>>>>
>>>>
>>>>
>>>>     El 10 de junio de 2015, 20:17, Diego<diegogeid en gmail.com>  <mailto:diegogeid en gmail.com>  escribió:
>>>>>     Hola, saludos a todos.
>>>>>
>>>>>     Aparentemente estoy teniendo un error conceptual. Copio el código
>>>>>     abajo. Alguien podría ayudarme?
>>>>>
>>>>>     Al intentar acceder a un elemento del aray desde el main no tengo
>>>>>     problemas, pero al intentar acceder desde una función el programa
>>>>>     retorna al sistema operativo un código de error (0xC0000005) y
>>>>>     porsupuesto que no continúa.
>>>>>
>>>>>     Según los printf, los punteros apuntan a la misma posicion de memoria
>>>>>     tanto en el main como en la función, que estoy haciendo mal?
>>>>>
>>>>>     PD: estoy compilando en Windows mediante Code::Blocks en Windows
>>>>>     mediante gcc, el error que da, según google, corresponde a una
>>>>>     violación de acceso a memoria.
>>>>>
>>>>>     Saludos y gracias!
>>>>>
>>>>>     ----------------------------------------------
>>>>>
>>>>>     #include <stdio.h>
>>>>>     #include <stdlib.h> //No es necesario
>>>>>
>>>>>     void probar(float **referencia)
>>>>>     {
>>>>>
>>>>>          printf("La posición de memoria donde empieza el array
>>>>>     multidimensional es %p\n", referencia);
>>>>>
>>>>>     //No imprime el siguiente printf y vuelve al ssitema con un error
>>>>>     0xC0000005
>>>>>
>>>>>          printf("test: %f %f...!\nPuntero: %p\n", referencia[0][0],
>>>>>     referencia[0][1], referencia);
>>>>>     }
>>>>>
>>>>>     int main()
>>>>>     {
>>>>>          float test[5][5]={1, 2, 3, 4, 5};
>>>>>
>>>>>          printf("La posición de memoria donde empieza el array
>>>>>     multidimensional es %p\n", test);
>>>>>
>>>>>          printf("test: %f %f...!\nPuntero: %p\n", test[0][0], test[0][1],
>>>>>     test);
>>>>>
>>>>>          probar(test);
>>>>>
>>>>>          return 0;
>>>>>     }
>>>>>
>>>>>     _______________________________________________
>>>>>     Lista de correo CconclaseCconclase en listas.conclase.net  <mailto:Cconclase en listas.conclase.net>
>>>>>     http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
>>>>>     Bajas:http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>>>>
>>>>     --
>>>>     Andrés Felipe Valencia P
>>>>     MSc student
>>>>     ALaRI - Advanced Learning and Research Institute USI - Università della
>>>>     Svizzera Italiana
>>>>     Via Giuseppe Buffi 13, Lugano CH-6904, Switzerland
>>>>     Mobile: + 41 076 822 27 57
>>>>
>>>>     _______________________________________________
>>>>     Lista de correo CconclaseCconclase en listas.conclase.net  <mailto:Cconclase en listas.conclase.net>
>>>>     http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
>>>>     Bajas:http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>>     _______________________________________________
>>     Lista de correo CconclaseCconclase en listas.conclase.net  <mailto:Cconclase en listas.conclase.net>
>>     http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
>>     Bajas:http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>     _______________________________________________
>     Lista de correo Cconclase Cconclase en listas.conclase.net
>     <mailto:Cconclase en listas.conclase.net>
>     http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
>     Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>
>
>
>
> _______________________________________________
> Lista de correo Cconclase Cconclase en listas.conclase.net
> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20150615/2831eadd/attachment-0001.html>


Más información sobre la lista de distribución Cconclase