Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: PabloPbl en 13 Diciembre 2015, 19:37 pm



Título: Pequeña duda sobre punteros
Publicado por: PabloPbl en 13 Diciembre 2015, 19:37 pm
Se que si yo hago esto:
Código
  1. char *cadena = "Hola";
Se reserva una determinada cantidad de bytes en alguna parte de la memoria, en este caso, 4 bytes, por que son 4 caracteres.

Pero si ahora yo hago esto:
Código
  1. char *cadena = "Sol";
Se reservara 3 bytes mas para esta cadena, y acá mi pregunta:
¿Que pasa con los otros 4 bytes que reserve para la cadena "Hola", se reemplaza por estos?
Supongamos que se reemplaza, entonces, quedaría un byte libre, con la letra "a", ¿como haría para liberar ese espacio inútil? Ya que esta cadena solo ocupa 3 letras y sobraría 1, que había reservado anteriormente.
Espero me haya dado a explicar.

Mil gracias y espero me disculpen por molestar tanto, estoy estudiando C++ y me surgieron un montón de dudas y no las encontré en la web  :-\


Título: Re: Pequeña duda sobre punteros
Publicado por: fary en 13 Diciembre 2015, 19:58 pm
No puedes declarar dos variables con el mismo nombre en la misma función  :xD

Si hubieras probado te habrías dado cuenta.



Título: Re: Pequeña duda sobre punteros
Publicado por: class_OpenGL en 13 Diciembre 2015, 20:52 pm
A parte de lo que dice PabloPbl, con la primera cadena se reserva espacio para CINCO caracteres. El último carácter indica el fin de la cadena (equivale a 0). Por ejemplo, la declaración
Código
  1. char cadena[] = "Hola";
equivale a la declaración
Código
  1. char cadena[] = {'H', 'o', 'l', 'a', '\0'};
Si no se pusiera ese carácter, no sabríamos el final de la cadena.


Título: Re: Pequeña duda sobre punteros
Publicado por: 0xFer en 13 Diciembre 2015, 21:14 pm
Hola Pablo, cuánto tiempo sin hablar.

Citar
¿Que pasa con los otros 4 bytes que reserve para la cadena "Hola", se reemplaza por estos?

cadena al principio apunta a "Hola" en donde sea que esté el "H" pues allí es donde está apuntando, siempre que crees una cadena así como lo estás haciendo siempre se agrega un '\0' al final de la cadena( como ya te han dicho), es como si le dijeras al compilador que allí es donde termina la cadena. Ahora cuando haces que cadena apunte a "Sol" entonces la cadena "Hola" seguirá existiendo en la computadora, el problema es que ya no vamos a saber en dónde( al menos que con otro puntero guardes la dirección a la que apuntaba cadena al principio, cuando apuntaba a "Hola"), como ahora cadena apunta a "Sol" y como "Hola" aún sigue existiendo en la computadora pues cadena tendrá otra dirección de memoria.

Entonces al hacer esas asignaciones terminas perdiendo los punteros( quién sabe en dónde irán a terminar), luego creo que no se podrán liberar( el que se pierde, en este caso se pierde la dirección en donde se aloja "Hola", es como que un puntero no tiene memoria de las cosas a las que apunta, si lo cambias ya no se acordará de dónde apuntaba anteriormente).

Si es C++ entonces tienes a new y delete para manejar memoria dinámica, con eso como que te obligan a liberar la memoria cuando ya no lo estas utilizando, sino pues tienes que confiar a que la computadora libere la memoria( tipo java (xD)).

Ve fijándote en la dirección:

Código
  1.     char* cadena = "Hola";
  2.     printf("Dirección %d ",&(*cadena));
  3.  
  4.     cadena = "Sol";
  5.     printf("Dirección %d ",&(*cadena));

la dirección de cadena cambia. Luego también puedes guardar a "Hola" en otro puntero:

Código
  1.     char* cadena = "Hola";
  2.     char* cadena2 = cadena; //salvamos a cadena antes de cambiar a lo que apunta
  3.  
  4.     cadena = "Sol";
  5.  
  6.     printf("%s",cadena);
  7.     printf("%s",cadena2);

Ahora cuando el programa termine se libera cadena y cadena2 tranquilamente.


Título: Re: Pequeña duda sobre punteros
Publicado por: PabloPbl en 13 Diciembre 2015, 23:54 pm
Hola, muchas gracias a todos por la orientación, mas claro imposible  ;-)

Pero tengo una duda mas  :P

Si bien se que al hacer uso de esto, en una instrucción:
Código
  1. *puntero
Estoy obteniendo el valor de la dirección de memoria que se esta apuntando con el puntero.
Corrijanme si me equivoco.

Ahora quiero lograr obtener la dirección de memoria del valor que se esta apuntando con el puntero, me explico:

Código
  1. char *puntero = "Hola";

¿Como podría obtener la dirección de memoria en donde se encuentra el caracter "H"?

He intentado hacerlo así:
Código
  1. char *puntero = "Hola";
  2. cout << &(*puntero) << endl;

Pero lo único que hace es mostrarme la cadena entera, ¿por que pasa esto? ¿No se supone que me debería mostrar la dirección de memoria de lo que esta apuntando puntero?

Citar
Hola Pablo, cuánto tiempo sin hablar.
Hola Bro ;D si, anduve muy liado con los estudios(no me dejaban ni respirar).  >:(
Pero bueno, espero poder volver al grupo así hacemos algo, si es que siguen  :xD

Saludos.


Título: Re: Pequeña duda sobre punteros
Publicado por: 0xFer en 14 Diciembre 2015, 00:09 am
Cast a void*:

Código
  1. char *cadena = "Hola";
  2. cout << "Dirección: " << (void*)cadena << "\n";
  3.  

Lo de arriba sólo funciona en C, disculpa por eso.


Título: Re: Pequeña duda sobre punteros
Publicado por: mester en 24 Diciembre 2015, 01:25 am
Al menos en C, para hacer esto:
Código
  1. char *cadena = "Hola";

Antes debes reservar memoria con alguna función como malloc o calloc:
Código
  1. char *cadena = (char *)calloc(5,sizeof(char));
  2. strcpy(cadena,"Hola");

Y por último con strcpy asignar a cadena una frase.



Título: Re: Pequeña duda sobre punteros
Publicado por: Zekkk en 25 Diciembre 2015, 07:21 am
Si tu haces:

Código:
char* cadena = "Hola";

No se reservan 4 bytes en alguna parte de la memoria. Se reservan 5 bytes(mas \0) en lo que se llama "stack" que es basicamente memoria eficiente y bastante limitada.

Cuando tu haces esto:

Código:
cadena = "Sol";

Que es lo que imagino que quisiste hacer, entonces has perdido la direccion donde esta "Hola" y tu puntero ahora apunta a "Sol" que son 4 bytes. Ahora, Sol no reemplaza a Hola de ninguna forma. Es decir, si crees que sucede esto "Sol\0a\0" te digo que eso no es lo que esta pasando, pero asumamos que es asi.

Entonces tenemos memoria que no nos sirve ocupando espacio y que debemos hacer para liberarla? Nada, porque fue reservada en el stack y la computadora maneja la memoria del stack por ti asi que no te preocupes por eso.

Ahora para elaborar un poco mas la respuesta de tu pregunta original y de paso responder la segunda tenemos que entender como se reserva la memoria en el stack. Supongamos que tenemos tu codigo original:

Código:
char* cadena = "Hola";

y la direccion de la memoria donde se encuentra H es 4195924 . Hola ocupa 5 bytes entonces el char final del string "Hola" esta en 4195929(que es \0). Ahora supongamos que tenemos:

Código:
cadena = "Sol";

Y la memoria es 4195949, entonces si haces
Código:
printf("%s", cadena - 20);
lo que veas deberia ser Hola.

Para obtener la direccion de la memoria tienes que recordar que se trata de un numero. Entonces
Código:
printf("%d", cadena);
te da la direccion de la memoria. El estilo para hacerlo en C++ seria:
Código:
std::cout << (int)cadena;


Título: Re: Pequeña duda sobre punteros
Publicado por: Eternal Idol en 25 Diciembre 2015, 13:50 pm
nonpromisc: si se puede hacer eso, son literales de cadena.

Zekkk: no van en la pila (si el puntero en si mismo si es una variable local) sino en la sección de datos de solo lectura, por eso si tratas de escribir en ellos se produce una excepcion no controlada.

Código
  1. #include <cstdio>
  2.  
  3. void main()
  4. {
  5.    //char cadena[] = "Hola"; //esto si va en la pila
  6.    char *cadena = "Hola";
  7.    *cadena = 'B'; //kaboom
  8.    printf(cadena);
  9. }


Título: Re: Pequeña duda sobre punteros
Publicado por: MAFUS en 25 Diciembre 2015, 15:03 pm
Cintunuando con la explicación de Eterna Idol, decir que una forma de poner en la pila una cadena es mediante el uso de arrays de carácteres:

Código
  1. char str[] = "Una cadena";

Siempre y cuando str sea una variable local. En este caso C crea espacio en la pila y genera el código para copiar 'Una cadena' en ese espacio reservado, mas un caracter nulo, con lo que 'Una cadena' no existe en otro sitio que el archivo fuente de C.

Pero no se puede definir de la manera siguiente
Código
  1. char str[];
  2. str = "Una cadena";

Por el hecho de que str es un puntero estático, no puede apuntar a otro sitio, y ahora "Una cadena" es una constante que se guarda en la zona de memoria de solo lectura. C no genera codigo para copiar el valor sino que interpreta que se quiere que str apunte a la cadena, lo que es ilegal.


Título: Re: Pequeña duda sobre punteros
Publicado por: kondrag_X1 en 25 Diciembre 2015, 16:40 pm
Una pregunta

Para evitar esos problemas se usa malloc reservando y posteriormente liberando la memoria, verdad?


Título: Re: Pequeña duda sobre punteros
Publicado por: Zekkk en 26 Diciembre 2015, 00:56 am
Correcto, esta en la sección de datos de solo lectura y el puntero en si en el stack. Y no kondrag, no se reserva memoria usando malloc a menos que realmente lo necesites porque reservar memoria en el "heap" es mucho mas lento que en el stack. Considera que para reservar memoria con malloc() tienes que buscar un bloque de memoria lo suficientemente grande y dividirlo y para empeorar las cosas luego debes liberarlo usando free(). Por otra parte para resevar memoria en el stack solo tienes que cambiar un puntero.

Es decir, solo usa malloc cuando sea absolutamente necesario.


Título: Re: Pequeña duda sobre punteros
Publicado por: kondrag_X1 en 26 Diciembre 2015, 01:54 am
y cuando es necesario? siempre he tenido esa duda


Título: Re: Pequeña duda sobre punteros
Publicado por: Zekkk en 26 Diciembre 2015, 02:08 am
Cuando necesitas acceso a una gran cantidad de memoria. Por ejemplo si quisieras un array bastante grande, o cuando necesitas mantener una variable por mucho tiempo como por ejemplo para una lista enlazada o algo asi.


Título: Re: Pequeña duda sobre punteros
Publicado por: 0xFer en 26 Diciembre 2015, 02:12 am
y cuando es necesario? siempre he tenido esa duda

Si antes de la compilación no sabes cuánta memoria vas a utilizar para alojar tus variables entonces para no tener que reservar una enorme cantidad de memoria en tiempo de compilación y que al final no vas a terminar de usar entonces reservas memoria en tiempo de ejecución cuando ya conozcas cuánta memoria vas a necesitar.

Imagina que reservas memoria en tiempo de compilación para 200 variables pero al final terminas usando sólo 40 entonces habrás desperdiciado 160, si es posible entonces reservas memoria sólo para esas 40 variables con memoria dinámica. Aunque personalmente sólo uso memoria dinámica cuando sé que la cantidad de memoria que se perderá es grande en caso de no usarla.


Título: Re: Pequeña duda sobre punteros
Publicado por: kondrag_X1 en 26 Diciembre 2015, 12:44 pm
ok, gracias a todos yo reservaba memoria siempre que recibía un paquete cuando programa servidores y clientes en C.