Pequeña duda sobre punteros

Iniciado por PabloPbl, 13 Diciembre 2015, 19:37 PM

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

PabloPbl

Se que si yo hago esto:
Código (cpp) [Seleccionar]
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 (cpp) [Seleccionar]
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  :-\

fary

No puedes declarar dos variables con el mismo nombre en la misma función  :xD

Si hubieras probado te habrías dado cuenta.

Un byte a la izquierda.

class_OpenGL

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 (c++) [Seleccionar]
char cadena[] = "Hola";
equivale a la declaración
Código (c++) [Seleccionar]
char cadena[] = {'H', 'o', 'l', 'a', '\0'};
Si no se pusiera ese carácter, no sabríamos el final de la cadena.

Programador aficionado. Me quiero centrar en programar videojuegos. La API que uso para crearlos es OpenGL

0xFer

#3
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 (cpp) [Seleccionar]

    char* cadena = "Hola";
    printf("Dirección %d ",&(*cadena));
   
    cadena = "Sol";
    printf("Dirección %d ",&(*cadena));


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

Código (cpp) [Seleccionar]

    char* cadena = "Hola";
    char* cadena2 = cadena; //salvamos a cadena antes de cambiar a lo que apunta
   
    cadena = "Sol";
   
    printf("%s",cadena);
    printf("%s",cadena2);


Ahora cuando el programa termine se libera cadena y cadena2 tranquilamente.
Código (java) [Seleccionar]
int getRandomNumber(){
    return 4; //chosen by fair dice roll
              //guaranteed to be random
}

PabloPbl

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 (cpp) [Seleccionar]
*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 (cpp) [Seleccionar]
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 (cpp) [Seleccionar]
char *puntero = "Hola";
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?

CitarHola 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.

0xFer

#5
Cast a void*:

Código (cpp) [Seleccionar]

char *cadena = "Hola";
cout << "Dirección: " << (void*)cadena << "\n";


Lo de arriba sólo funciona en C, disculpa por eso.
Código (java) [Seleccionar]
int getRandomNumber(){
    return 4; //chosen by fair dice roll
              //guaranteed to be random
}

mester

Al menos en C, para hacer esto:

char *cadena = "Hola";


Antes debes reservar memoria con alguna función como malloc o calloc:

char *cadena = (char *)calloc(5,sizeof(char));
strcpy(cadena,"Hola");


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

Justicia es dar a cada uno lo que se merece

Zekkk

Si tu haces:

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:

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:

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:

cadena = "Sol";

Y la memoria es 4195949, entonces si haces 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 printf("%d", cadena); te da la direccion de la memoria. El estilo para hacerlo en C++ seria:
std::cout << (int)cadena;

Eternal Idol

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 (c++) [Seleccionar]

#include <cstdio>

void main()
{
    //char cadena[] = "Hola"; //esto si va en la pila
    char *cadena = "Hola";
    *cadena = 'B'; //kaboom
    printf(cadena);
}
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

MAFUS

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:

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
char str[];
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.