Hack x Crack - Comunidad de Seguridad informática

Programación => C / C++ => Mensaje iniciado por: iomegahdd en Diciembre 25, 2014, 01:09:48 pm

Título: [C] Arrays con tamaño variable (Ayuda)
Publicado por: iomegahdd en Diciembre 25, 2014, 01:09:48 pm
Buenos días a todos!

Ayer estaba en una de mis 'Tardes de C' y empecé a hacer una librería en C para trabajar con números infinitos (tan infinitos como la RAM ;D) para lo que he decidido usar arrays. De momento guardo un dígito por byte, lo que es ineficiente, pero ya me dedicare a ello cuando termine el desarrollo. (Lo ideal sería guardar cada dígito en una variable de 4 Bits e incluso en hexadecimal para ocupar los 4 Bits completamente!!)
He llegado a un punto en el que tengo que tengo que declarar un array unidimensional con una longitud que viene dada por una variable calculada por el programa. Sería algo tal que así:
Código: [Seleccionar]
const short longitud = (sizeof(dato1) < sizeof(dato2)) ? sizeof(dato2) : sizeof(dato1);
unsigned char array[longitud];

Esto me lo acepta el compilador, pero al ser una variable local cuando salgo de la función que crea el array se sobrescribe, problema que solucionaría usando un simple static para que mantuviera el estado después del return de la función, pero el code me da error:
Código: [Seleccionar]
static unsigned char array[longitud];
He pensado en declararlo en la función main y pasarlo como parámetro a la función pero no puedo porque se necesitan unos cálculos previos para obtener la longitud del array que deberían quedar integrados en la librería.

Y esa es mi pregunta: Se les ocurre algo para solucionar esto?

Un saludo y gracias de antemano! ;)

[EDITADO]

Aquí el code de lo que llevo de la función suma:
Spoiler
Código: C
  1. //Función suma (Quedará dentro de librería). Recibe los dos números a sumar así como su longitud
  2. unsigned int* suma(unsigned char num1[], short len1, unsigned char num2[], short len2)
  3. {
  4.     short count; //Variable para contador
  5.     unsigned char *res = NULL, *oldres = NULL; //Array del resultado
  6.     unsigned int *sav = NULL, z = 0;// Array que se devuelve con el return
  7.     unsigned int baselen = (len1 > len2) ? len1+1 : len2+1; //Longitud del resultado
  8.     short dif1 = baselen - len1 , dif2 = baselen - len2, pos1, pos2; //Variables de control
  9.  
  10.     //Reservamos espacio para arrays
  11.     //res = (char *)realloc(res, baselen);
  12.     res = oldres = (char *)malloc(baselen);
  13.     sav = (int *)malloc(2);
  14.  
  15.     for(count = 0; count < baselen; count++)
  16.     {
  17.         *(res+count) = 0; //Inicializamos el array del resultado a 0
  18.     }
  19.  
  20.     //Barremos los números de la posición más alta del array a la menor
  21.     for(count = baselen-1; count >= 0; count--)
  22.     {
  23.         pos1 = (count)-dif1;
  24.         pos2 = (count)-dif2;
  25.  
  26.         //Con los IF evitamos salirnos de los arrays mientras sumamos
  27.         if((pos2 < 0) && (pos1 < 0))
  28.         {
  29.             ;
  30.         }
  31.         else if(pos1 < 0)
  32.         {
  33.             *(res+count) = *(res+count) + num2[pos2];
  34.         }
  35.         else if(pos2 < 0)
  36.         {
  37.             *(res+count) = *(res+count) + num1[pos1];
  38.         }
  39.         else
  40.         {
  41.             *(res+count) = *(res+count) + num1[pos1] + num2[pos2];
  42.         }
  43.  
  44.         //IF para control de sumas mayores a 10
  45.         if(res[count] >= 10)
  46.         {
  47.             *(res+count-1) = (*(res+count)/10);
  48.             *(res+count) = *(res+count) - (*(res+count)/10)*10;
  49.         }
  50.     }
  51.  
  52.     for(count = 0; count < baselen; count++)  //Deteccion del numero de 0 de más que hay a la izquierda
  53.     {
  54.         if(*(res+count) == 0)                 // EJ:     01845  -> 1 cero de más
  55.         {                                     //         _
  56.             z++;
  57.         }
  58.         else
  59.         {
  60.             break;
  61.         }
  62.     }
  63.     if(z != 0)                               //Eliminación de los ceros y redireccion de memoria con el nuevo array
  64.     {
  65.         baselen = baselen-z;                 //EJ:       01845 -> 1845
  66.         res = realloc(res,baselen);
  67.         for(count = z; count < baselen+z; count++)
  68.         {
  69.           *(res+count-z) = *(oldres+count);
  70.         }
  71.         //free(oldres);  ->>> Esta línea es necesaria?? <<<-------------------------------------------------
  72.     }
  73.  
  74.     //for(count = 0; count < baselen; count ++){printf("%d", *(res+count));}puts("");
  75.  
  76.     sav = &res;            //Creamos un array que devolveremos con los datos :
  77.     *(sav+1) = baselen;        //1.- Longitud del array del resultado 2.- Puntero al resultado
  78.  
  79.     return sav;  //Devolvemos array [*Resultado, longitud]
  80. }

Les cuento.
La función devuelve una dirección de memoria a un array de longitud 2.
En su primera posición guarda la dirección de memoria del array del resultado y en la segunda guarda la longitud de este.

NOTA: Si hay algo muy muy mal avisen :)
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: C_printfer en Diciembre 25, 2014, 01:53:37 pm
Hola, no sé si entiendo bien tu problema, igual te digo una tontería pero... ¿Por qué no pasas el array por referencia a la función main en lugar de hacerlo por valor?
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: iomegahdd en Diciembre 25, 2014, 02:20:29 pm
No se si te he entendido.
Lo que estoy haciendo es mediante el return de la función devolver un puntero al primer elemento del array, pero el problema es que cuando voy a leer el dato de la dirección de memoria ha cambiado, porque se libera el espacio al salir de la función que creó el array. Es ahí cuando entra el static en juego, pero como da error...

Gracias igualmente!!!
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: tryger en Diciembre 25, 2014, 07:26:25 pm
hola, para lo que buscas existe la funcion estandar malloc, que lo que hace basicamente es asignar memoria a una variable.
Aquí tienes toda la info -> http://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm (http://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm)
Y aqui un poco sobre memoria dinamica -> https://en.wikipedia.org/wiki/C_dynamic_memory_allocation (https://en.wikipedia.org/wiki/C_dynamic_memory_allocation)

salu2  ;)
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: iomegahdd en Diciembre 25, 2014, 07:52:13 pm
Muchísimas gracias, creo que es lo que buscaba!
Mañana le echaré un vistazo y ya os cuento. A ver si dentro de poco termino la librería, que como me meta en exámenes...  ;D

Dew y feliz navidad!
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: C_printfer en Diciembre 26, 2014, 01:50:02 pm
Pero vamos a ver, que yo me pierdo... Claro que está la función malloc, pero si lo quiere es un array de números infinitos, no entiendo de qué le puede servir.

No obstante, ya digo, que no estoy seguro de entender su problema.

S2!
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: animanegra en Diciembre 26, 2014, 01:58:24 pm
Pues porque primero declara una variable como puntero. int *tabla;
dentro de la funcion cuando ya sepa la longitud hace el malloc y ya puede almacenar.
No obstante el uso de variables globales a mi parecer y opinion es una chapuzilla, yo devolveria un puntero al que le he hecho dentro un malloc y punto.
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: ACK en Diciembre 27, 2014, 07:55:02 pm
El malloc no sirve por si solo... Por más que en la memoria puedas almacenar números infinitos con malloc, el procesador no puede trabajar con todo eso. Tiene un limite. (Depende de si es 32 o 64 bits).
Por eso es necesario crear una libreria.

Por otro lado, no te recomiendo usar arrays. Usa memoria dinámica. Mira, tienes que hacer algo como esto:

Numero 1------ Cada espacio es un byte =
[00010001][10010101][10101010][11101101][11010110][11011010][11111111]

Numero 2----- Cada espacio es un byte =
                   [10110011][00010110][00001010][11100000][00000000][11111111]

Esos espacios en memoria los reservas usando malloc. Ahora, para sumar o restar, lo haces de DERECHA a IZQUIERDA. Igual que como lo harías en una hoja, pero byte a byte. No tienes que olvidarte de almacenar el carry. Osea, los valores que sobran. Por ejemplo:
  1111111
  11111111 = 255
  11111111 = 255
  -------------
111111110 = 510

Entonces, ahora, en la ultima posición del arreglo:
                                                                                        +1 -> al final por el carry
[********][********][********][********][********][11111110]

Si buscas por Internet, estoy seguro que ya encuentras librerías echas. Te pueden servir para darte una mano. No se si me entendiste :P. Es una respuesta bastante apresurada... Cualquier cosa vuelves a preguntar.

Abrazo! :)
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: iomegahdd en Diciembre 27, 2014, 09:28:51 pm
Bueno, no sabía que daría para tanto el hilo   ;D

De momento he implementado la función con malloc's y va muy bien. Tengo un problemilla con lo de liberar memoria, ya que si hago la función recursiva  (EJ con función suma: a = a+b) no libera los arrays pero espero solucionarlo pronto. Creo que puede venir de que no se si hay que usar free() despues de realloc().

Sobre lo que me comentas, ACK, creo que te refieres a que use arrays de tipo char reservados con malloc() y codifique el número en base255  (11111111 = 255). Creo que es como lo que dije de optimizar memoria usando 4 bits por dígito y codificándolo en hexadecimal (1111 = F). Así se ocuparían todos los bits de las variables en lugar de tener el máximo en 00001001 = 9(DEC)

De momento, en el desarrollo he optado por usar base 10 directamente y malgastar cada byte con un dígito decimal. Lo que hago es exactamente eso: Sumar como si fuera sobre papel (derecha a izquierda y contando acarreos).

La verdad es que seguro que existen librerías hechas, pero este verano volví a C y como andaba falto de ideas busqué ejercicios para hacer en C.  Uno de ellos era ver si un número introducido era primo o no, y como me gusta todo esto de la ciencia pues hice un programa que iba calculándolos a partir del 0. Pero el problema es que claro, puedo operar tipo a+b; mientras los números no superen las variables establecidas en C pero... y por encima? Entonces pensando y preguntando acabé optando por los arrays.
Además, siempre gusta ver que algo que has hecho tu funciona(o no...) :)

Quitando todo esto me acabas de solucionar una cosa que tenía en mente!  Esto de tener la cabeza tan desordenada... XD

No se si te referías a esto ACK, y tampoco si tiene sentido todo lo que he dicho.
Muchas gracias por la ayuda. Ahora actualizo el hilo con el código que llevo de la función(Si hay alguna burrada no me la tengáis en cuenta :P)
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: animanegra en Diciembre 29, 2014, 12:04:36 pm
Libera los mallocs cuando debes, que como sigas ampliando la libreria se te olvidará y despues vendran los memory leaks y los lloros y el porque lo hice, y el no me queda otra opcion que el suicio o el alcohol...

No en serio, hay que ser organizados con los mallocs y liberarlos cuando toca, que si no despues te crearán unos dolores de cabeza increibles.
Título: Re:[C] Arrays con tamaño variable (Ayuda)
Publicado por: iomegahdd en Diciembre 30, 2014, 09:54:37 pm
Claro, pero el problema es que no los puedo liberar antes de leerlos, por lo que los tendría que liberar la función que llama a la función suma y al final los free() acabarían quedando fuera de la librería.