[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