Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] Función que devuelve un puntero

Estas en el tema de Función que devuelve un puntero en el foro de C/C++ en Foros del Web. Hola, Tengo una duda acerca de una función que devuelva un puntero en C. Tengo una función declarada de la siguiente forma: @import url("http://static.forosdelweb.com/clientscript/vbulletin_css/geshi.css"); Código ...
  #1 (permalink)  
Antiguo 15/07/2015, 02:30
 
Fecha de Ingreso: mayo-2015
Mensajes: 15
Antigüedad: 9 años, 5 meses
Puntos: 0
Función que devuelve un puntero

Hola,

Tengo una duda acerca de una función que devuelva un puntero en C.

Tengo una función declarada de la siguiente forma:

Código C:
Ver original
  1. char ** myfunction()
  2. {
  3.   char ** valor;
  4.   ...
  5.   return valor;
  6. }

A la hora de llamar a esta función y asignarle el valor devuelto a un puntero, ¿cómo debo hacerlo? He probado de la siguiente forma pero me da problemas..

Código C:
Ver original
  1. int main
  2. {
  3.   char ** variable;
  4.   variable=(char**)malloc(10*sizeof(char*));
  5.  
  6.    variable = myfunction();
  7.    return 0;
  8. }

Muchas gracias!
  #2 (permalink)  
Antiguo 15/07/2015, 03:35
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Función que devuelve un puntero

Para entender mejor tu problema, quita los punteros. Imagínate este código:

Código C++:
Ver original
  1. int func( )
  2. {
  3.   return 4;
  4. }
  5.  
  6. int main( )
  7. {
  8.   int variable = 10;
  9.   variable = func( );
  10.   printf( "%d\n", variable );
  11. }

¿Qué valor almacena variable al final del programa? queda claro que valdrá 4.

Vale, pero esto era muy facil... y si le ponemos un puntero doble? Veamos

Código C++:
Ver original
  1. int** func( )
  2. {
  3.   return (int**)4;
  4. }
  5.  
  6. int main( )
  7. {
  8.   int** variable = (int**)10;
  9.   variable = func( );
  10.   printf( "%d\n", (int)variable );
  11. }

He añadido algunos cast para evitar warnings, por lo demás queda claro que el programa es el mismo... ¿qué valor se imprimirá ahora? Nuevamente, la respuesta vuelve a ser 4.

Un operador de asignación sustituye un valor por otro... así de simple. Si estamos usando variables por valor ( int, char, double, etc ) se machacará el valor de la variable... si usamos punteros, dado que los punteros almacenan posiciones de memoria, se sustituirá la posición de memoria gestionada por el puntero.

En tu programa lo que sucede es que en la línea 4 haces una reserva de memoria y almacenas la posición de dicha reserva en variable. Pero luego, en la línea 6 haces que variable apunte a otra región de memoria, que será la que te devuelve myfunction. Esto provoca que la memoria reservada en la línea 4 ya no sea accesible (no tienes ninguna variable que te diga dónde se encuentra), por lo que no podrás liberar esa memoria... esto es una fuga de memoria o laguna de memoria y es uno de los problemas más comunes al trabajar con memoria dinámica.

¿Soluciones? tranquilo que las hay. Te expongo un par de ellas:

1. Haces que myfunction se encargue de reservar la memoria:

Código C:
Ver original
  1. char** myfunction( )
  2. {
  3.   char** to_return = (char**)malloc(10*sizeof(char*));
  4.  
  5.   // ... operaciones sobre to_return ...
  6.  
  7.   return to_return;
  8. }
  9.  
  10. int main( )
  11. {
  12.   char ** variable = myfunction();
  13.  
  14.   return 0;
  15. }

2. myfunction recibe como parámetro el puntero sobre el que debe operar. Al recibir un puntero, los cambios que se hagan en la memoria apuntada se verán reflejados al abandonar la función.

Nota que ahora, myfunction recibe también el número de elementos, esto te permite trabajar con arrays de diferentes tamaños.

Código C:
Ver original
  1. void myfunction( char** matriz, int numElementos )
  2. {
  3.   // ... operaciones sobre matriz ...
  4. }
  5.  
  6. int main( )
  7. {
  8.   char ** variable = (char**)malloc(10*sizeof(char*));
  9.  
  10.   myfunction( variable, 10 );
  11.  
  12.   return 0;
  13. }

Y, por cierto, que no se te olvide liberar toda la memoria que hayas reservado. Empieza a adquirir esta costumbre desde el principio para evitar sorpresas desagradables con programas más grandes.

Un saludo.
  #3 (permalink)  
Antiguo 16/07/2015, 02:19
 
Fecha de Ingreso: mayo-2015
Mensajes: 15
Antigüedad: 9 años, 5 meses
Puntos: 0
Respuesta: Función que devuelve un puntero

Hola eferion,

Gracias por tu respuesta; de nuevo, perfectamente explicado.

Es cierto que el tema de liberación de memoria es algo que suelo olvidar y después me provoca muchos quebraderos de cabeza :). En este caso, entiendo que el código quedaría de la siguiente manera, para liberar la memoria reservada:

Código C:
Ver original
  1. int main( )
  2. {
  3.    char ** variable = (char**)malloc(10*sizeof(char*));
  4.  
  5.    myfunction( variable, 10 );
  6.  
  7.    free (variable);
  8.  
  9.    return 0;
  10. }

La cuestión es que el código me compila y la aplicación se ejecuta, pero aparece un error al compilar que me mosquea (estoy utilizando Visual Studio 2010):

IntelliSense: una referencia de tipo "int &" (no calificado constante) no se puede inicializar con un valor de tipo "char**"

El error hace referencia al uso de variable en la siguiente linea:

Código C:
Ver original
  1. myfunction( variable, 10 );

¿Sabes por qué aparece este error? ¿Realmente es un problema de compilación (ya que la aplicación se compila sin problemas?

Gracias de nuevo
  #4 (permalink)  
Antiguo 16/07/2015, 02:32
 
Fecha de Ingreso: mayo-2015
Mensajes: 15
Antigüedad: 9 años, 5 meses
Puntos: 0
Respuesta: Función que devuelve un puntero

Vale,

He cerrado Visual y lo he abierto de nuevo, y ya no me aparece el error. Así que, solucionado!!

Muchas gracias

Etiquetas: char, devuelve, int, puntero
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 00:52.