Codigo en CODEBLOCKS ( tampoco en DEV C ++ ) no se actualiza si cambio un valor

Iniciado por snoopty, 30 Noviembre 2021, 09:29 AM

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

snoopty

Hola ! El siguiente Codigo que busca imprimir la Dirección de Memoria Física de una Variable al tomar el valor 80 ( ya de por sí me arroja un valor inexacto, " 0X404004 " ), si cambio 80 por cualquier otro valor siempre vuelve a imprimir " 0X404004 " =

Código (cpp) [Seleccionar]
#include <iostream>
#include <conio.h>
using namespace std;


int numero = 10;

// " * " : OPERADOR UNARIO DE INDIRECCIÓN
//       : Indica q lo q sigue a continuación es un PUNTERO
int * puntero1;


int main( )
{
// " & " : OPERADOR DE DIRECCIONAMIENTO
puntero1 = & numero; // Con " & " logramos que puntero1
                     // APUNTE A LA DIRECCIÓN DE MEMORIA FÍSICA
                     // donde se encuentre EL ÚLTIMO VALOR
                     // q se le asignó a la Variable " numero "

                     // EN ESTE EJEMPLO devolverá
                     // LA DIRECCIÓN DE MEMORIA DEL VALOR 80
                     // porque en el cout NO LE ANTEPONGO
                     // a puntero1 " * "

numero = 80;

cout << puntero1 <<endl;

getch ();
}


Gracias por leer el mensaje. Saludos !


Eternal Idol

El valor es correcto, es un puntero y por lo tanto se escribe su direccion. Pero no entiendo, eso mismo esta escrito en los propios comentarios del programa ... ¿Quien los escribio?

Código (c++) [Seleccionar]
cout << *puntero1 <<endl;
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

snoopty

Los comentarios los pongo yo; la Dirección de Memoria correspondiente a 80 debería de ser " 0X4b8000 " .... por otra parte, como pongo en el título, si en vez de 80, a éste lo reemplazo por 50, 30, 15, 10, etc, luego de compilar SIEMPRE ME DEVUELVE como Dirección de Memoria " 0X404004 " .... no debería a caso tener cada Número ( " Valor " en el título ) una Dirección de Memoria diferente ???
Por todo esto es que hago la consulta.

Eternal Idol

Lamentablemente solo se puede llegar a esa conclusion si uno no entiende que es un puntero. Te recomiendo leer algun libro de C++ o cuanto menos algun tutorial sobre el tema.

PD. Las direcciones de memoria - virtuales - en S.O. modernos son dependientes de muchas cosas, no deberias jamas asumir que entre una ejecucion y otra seran iguales.
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

snoopty

1 ) Respecto de tu PD : mi inquietud iba por otro lado; yo asumía erráticamente que cambiando los valores de una misma Variable debería de obtener diferentes Direcciones de Memoria, lo que corroboré que no es así .....
(( pero Igualmente entiendo lo que explicaste, y es altamente valorable !!!!! ))

2 ).... pues ahora con otro ejemplo he visto que la memoria direccionada a partir de un puntero " afecta " sólo a la variable, independientemente del valor que se cambie, es decir, x + q yo cambie 80 x cualquier otro valor siempre el código me devolverá la Dirección Física de la Variable; sólo en el caso de que defina otra variable global, valiéndome de un mismo puntero // no haciendo falta definir otro // direccionador para ambas variables, obtendré, ahora sí, dos Direcciones de Memoria Física diferentes ( lo constato más aún si a a ambas variables les asigno el mismo Valor )

K-YreX

Cita de: snoopty en  1 Diciembre 2021, 10:02 AM
sólo en el caso de que defina otra variable global, valiéndome de un mismo puntero // no haciendo falta definir otro // direccionador para ambas variables, obtendré, ahora sí, dos Direcciones de Memoria Física diferentes ( lo constato más aún si a a ambas variables les asigno el mismo Valor )
Sólo aclarar que la variable da igual que sea global que local.

Para entendernos, cuando tú le dices al programa "crea una variable", el programa reserva un espacio para esa variable. Cada variable podríamos decir que tiene 2 partes:
  • Por un lado un identificador de esa variable. Un valor que representa unívocamente la variable -> Su dirección de memoria. No puede variar durante la ejecución.
  • Por otro lado el contenido almacenado en ese espacio. El valor que se guarda en esa variable. Puede variar durante la ejecución.

    Un ejemplo que puede ser un poco más complejo pero que si le das una vuelta y lo entiendes creo que habrás avanzado mucho. PD: Me inventaré las direcciones de memoria por simplificarlas y porque es imposible adivinar qué dirección de memoria se va a asignar a cada variable en cada ejecución. Eso no depende de nosotros.

    Antes del ejemplo, varios puntos que hay que tener claros:
  • Puntero: Variable que su contenido es siempre una dirección de memoria. Al ser así los punteros tienen 2 direcciones de memoria: una de ellas es su identificador y la otra es su contenido.
  • Operador * (asterisco): Desreferencia un puntero. Hace que el puntero no devuelva la dirección de memoria que tiene almacenada en su contenido sino que devuelve el contenido de esa dirección de memoria. Excepción: En la línea en que se define el puntero, el operador * no desreferencia, sólo indica que se está declarando un puntero.

    Suponemos que la posición de memoria 0x1234 contiene el valor 8
    Puntero p = 0x1234 -> Un puntero siempre contiene direcciones de memoria
    Mostrar p -> Muestra (el contenido de p): 0x1234
    Mostrar *p -> Muestra (el contenido de la dirección de memoria 0x1234): 8

  • Operador & (ampersand): Se puede aplicar a cualquier variable. Obtiene la dirección de memoria de esa variable (su identificador único e invariable) en vez de su contenido.

    Código (cpp) [Seleccionar]

    int main() {
      int a = 5; // El programa reserva la posicion 0x1 de la memoria (para a) y guarda en su interior el valor 1. Lo representare a partir de ahora como -> 0x1(5)

      int *p = &a; // El programa reserva la posicion 0x2 de la memoria (para p) y guarda en su interior la direccion de memoria de a (0x1) -> 0x2(0x1)
     
      cout << "El valor de a es: " << a << " y su direccion de memoria es: " << &a << endl; // Muestra: "El valor de a es: 5 y su direccion de memoria es: 0x1"
      cout << "El valor de p es: " << p << " y su direccion de memoria es: " << &p << endl; // Muestra: "El valor de p es: 0x1 y su direccion de memoria es: 0x2"
      cout << "Desreferenciamos p: " << *p << endl; // Muestra: "Desreferenciamos p: 5"

      // Ahora vamos a probar a cambiar valores a ver que pasa
      int b = 8; // El programa reserva la posicion 0x3 de la memoria (para b) y guarda en su interior el valor 8 -> 0x3(8)
      *p = b; // Que pasa aqui? No se cambia la direccion de memoria que contiene p (0x1). Se cambia el valor que hay dentro de 0x1 (5). 0x1 es la direccion de memoria que identifica a la variable a -> 0x1(8)
      cout << "El valor de a es: " << a << " y su direccion de memoria es: " << &a << endl; // Muestra: "El valor de a es: 8 y su direccion de memoria es: 0x1"
      // Hemos cambiado el contenido de a (5 -> 8) pero su direccion de memoria no varia, sigue siendo 0x1
      cout << "El valor de p es: " << p << " y su direccion de memoria es: " << &p << endl; // Muestra: "El valor de p es: 0x1 y su direccion de memoria es: 0x2" -> Como vemos esto no ha cambiado nada
      cout << "Desreferenciamos p: " << *p << endl; // Muestra: "Desreferenciamos p: 8" -> Esto si ha cambiado porque el contenido de 0x1 ahora es 8, no 5

      // Hasta aqui todo bien supongo. Asequible, pero... y ahora que?
      int **pp = &p; // El programa reserva la posicion 0x4 de la memoria (para pp) y guarda en su interior la direccion de memoria de p (0x2) -> 0x4(0x2)
      // Al usar ** estamos declarando un puntero a puntero. Un puntero que guarda como valor la direccion de memoria de otro puntero
      // Ahora vamos a comprobar que se sigue cumpliendo lo que decimos:
      cout << "El valor de pp es: " << pp << " y su direccion de memoria es: " << &pp << endl; // Muestra: "El valor de pp es: 0x2 y su direccion de memoria es: 0x4"
      cout << "Desreferenciamos pp: " << *pp << endl; // Muestra: "Desreferenciamos pp: 0x1"
      // Aclaremos la linea anterior: Al desreferenciar un puntero no mostramos la direccion de memoria que contiene sino el contenido de esa direccion de memoria
      // pp contiene 0x2 -> Al desreferenciar obtenemos el valor que se guarda dentro de la direccion 0x2 y si vamos a la linea de p vemos que el valor que guarda la direccion 0x2 es: 0x1  ​

      // Ahora entonces como *p devuelve una direccion de memoria (un puntero), podemos ver que contiene esa direccion de memoria (podemos desferenciarlo de nuevo):
      cout << "Desreferenciamos *pp: " << **pp << endl; // Muestra: "Desreferenciamos *pp: 8" -> Si *pp devuelve 0x1, el contenido de la direccion 0x1 es: 8
    }


    Se acabó el programa y la tabla de direcciones de memoria y contenido es:

    Variable a -> Direccion de memoria: 0x1 -> Contenido: 8
    Variable p -> Direccion de memoria: 0x2 -> Contenido: 0x1
    Variable b -> Direccion de memoria: 0x3 -> Contenido: 8
    Variable pp -> Direccion de memoria: 0x4 -> Contenido: 0x2



    RESUMEN
    -------------------
    - Todas las variables están formadas por una dirección de memoria y un contenido.
    - Las direcciones de memoria de cada variable las asigna el sistema operativo y no se pueden modificar.
    - El contenido de las variables puede ser un valor o una dirección de memoria (en el caso de los punteros). El contenido lo asignamos nosotros y se puede modificar.


    PD: Se me ha podido pasar algún error en el código. De ser así no dudéis en avisarme para corregirlo pues es un tema en el que la exactitud es muy importante.
    PD2: El código hay que estudiarlo sin prisa, hacer las pruebas que consideréis y preguntar cualquier duda que os pueda quedar.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;