funcion que devuelve un puntero de una variable static

Iniciado por fafafa01, 24 Enero 2017, 09:42 AM

0 Miembros y 1 Visitante están viendo este tema.

fafafa01

Buenas, me surgió la duda si es posible realizar una función que devuelva un puntero con la dirección de memoria de una variable static definida dentro de la función. por ejemplo pasarle la dirección de un arreglo definido como static dentro de una función.
la idea de esa función, es que quien la usa no se deba preocupar por el largo del arreglo debido a que este se crearía en la misma función (dentro de un if{..} por ejemplo).

MAFUS

La idea del static es que el dato se mantenga de llamada a llamada pero solo sea accesible para esa función. Si sabes que debes usar ese dato fuera de la función hazlo global.

ivancea96

Cita de: MAFUS en 24 Enero 2017, 10:08 AM
La idea del static es que el dato se mantenga de llamada a llamada pero solo sea accesible para esa función. Si sabes que debes usar ese dato fuera de la función hazlo global.

Lo que comenta el fafafa01 también es posible, y se puede utilizar para evitar que el programador que utilice la función se preocupe por la memoria.
Por ejemplo, una variable static es una posible forma de hacer la función localtime de la librería time.h/ctime: http://www.cplusplus.com/reference/ctime/localtime/

A parte de static, otro especificador remarcable es thread_local, que funciona como static, solo que cada nuevo thread tendrá su propia variable.

MAFUS

Vale, pues entonces ahora mismo no entiendo qué es lo que se pretende.

A ver un ejemplo.

ivancea96

Código (cpp) [Seleccionar]
int* getArray(unsigned int size){
    static int* array = nullptr;
    if(array != nullptr){
        delee[] array;
    }
   
    array = new int[size];
    return array;
}


Por ejemplo, ahí tienes una función que te da un array de X tamaño de cuya memoria no tienes que preocuparte (es un ejemplo trivial y poco útil, pero es un ejemplo).

Otra posibilidad es almacenar un estado. Por ejemplo, un generador de números aleatorios:

Código (cpp) [Seleccionar]
#include <ctime>
#include <iostream>

using namespace std;

int random(int newSeed = -1){
static int seed = 4974654;
if(newSeed != -1)
seed = newSeed;
else
seed = (seed + 784513)%530789;
return seed;
}

int main(){
random(time(0));
for(int i=0; i<10; i++)
cout << random()%10 << endl;
}

fafafa01

#5
que les parece este:


//convierte de entero a una cadena de char recursivamente.
char *itoa(int n){
static int i=1,c;
if(n/10){
char *t;
i++;
t=itoa(n/10);
t[c++]=abs(n%10)+'0';
return t;

}
else{
if(n<0){
static char s[i+1];
s[c++]='-';
s[c++]=-n+'0';
return s;
}
else{
static char s[i];
s[c++]=n+'0';
return s;
}
}
}

ivancea96

#6
No inicializas c*

Y bueno, static es útil pero, intenta no abusar xD
Código (cpp) [Seleccionar]
static char s[i];
Eso te va a generar un array de longitud i la primera vez que se llame a la función, y tendrá ese tamaño siempre.
Deberías suar memoria dinámica qsi quieres que sea dinámico.

Edito: Diría que la declaración static de ese array es ilegal, así que evítala. Punteros, memoria dinámica es la solución.


MAFUS

#8
Entiendo, aunque voy a decir que no es una técnica que me gusta mucho. Veo una fuga de memoria si el puntero es a un array dinámico y no se libera la memoria al final del programa (para sistemas donde el kernel no libere la memoria dinámica del programa cuándo este termine).



Edito:
Una solución es usando un array estático, así el programa limpia la memoria con normalidad. Por contra se debe pensar bien la cantidad de memoria a usar de antemano.


#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>


char * itoa(int num) {
   static char retval[12];
   size_t size;
   int negativo = num < 0;
   unsigned n = (unsigned)abs(num);
   
   size = (n? log10(n) : 0) + 1 + negativo;
   
   if(negativo)
       retval[0] = '-';
   
   retval[size--] = '\0';
       
   do {
       retval[size--] = n%10 + '0';
       n /= 10;
   } while(n);
   
   return retval;
}

int main() {
   printf("%s\n", itoa(INT_MAX));
   printf("%s\n", itoa(0));
   printf("%s\n", itoa(INT_MIN));
}