Voy a generalizar un poco aquí. La administración de memoria es un campo complicado, y cada sistema operativo hace las cosas de manera un poco diferente. Voy a hablar aquí sobre la arquitectura Intel (ya que eso es con lo que estoy más familiarizado) y podría no aplicarse a otros tipos de procesadores y definitivamente no se aplicará a los sistemas integrados. También voy a limitar mi discusión a “aplicaciones de usuario” y no al código del núcleo (Ring 3, versus Rings 0-2).
En los sistemas operativos modernos en los procesadores Intel, cada aplicación obtiene la misma vista de memoria (el “modelo plano”) que el sistema operativo divide en páginas, pero la aplicación ve poco de esto. Un programa no puede ver la memoria de ningún otro programa. Las direcciones de memoria que obtiene se “asignan” a la memoria “real” (o memoria virtual, espacio de intercambio, etc.). De una manera real, esto significa que sus direcciones de memoria son punteros que apuntan (a través de la acción de una Unidad de Administración de Memoria) a la memoria real.
Ocultar lo interno de la paginación significa que no tiene que saber ni preocuparse por las páginas que se le asignan o tener que asignar páginas específicamente y luego subdividirlas usted mismo (y la memoria física que controla puede ser contigua). El otro gran beneficio de esto es la capacidad de paginar o intercambiar (dependiendo de su sistema operativo) su memoria fuera de la memoria “real” del hardware y en dispositivos más lentos (SSD, disco duro, etc.) o memoria virtual real cuando otros programas tienen prioridad .
Por supuesto, incluso en el modelo plano, es probable que su variable tenga una dirección diferente para diferentes ejecuciones del programa, ya que la dirección de cualquier variable dada depende de lo que sucedió antes (si en una ejecución asignó 14Kb antes de asignar esa variable, estará en un lugar muy diferente al que asignó esa variable antes de los 14Kb). En un programa muy simple, es muy posible que obtenga la misma dirección exacta para la variable cada vez, pero sería una locura hacer suposiciones.
- ¿Por qué siento el deseo de violar la ley?
- He memorizado el Corán. ¿Debo incluir esto en mi ensayo personal para la universidad y proporcionarles un certificado si regreso a los Estados Unidos?
- Si creo que el aeropuerto Changi de Singapur es un buen negocio, ¿qué inversión puedo hacer para apostar?
- ¿Por qué siempre quiero saber por qué las cosas funcionan como lo hacen?
- Pienso en palabras en lugar de imágenes. ¿Cómo puedo cambiarlo? ¿Debería?
Bien, ahora que conocemos el panorama general, la dirección de una variable es una dirección en la memoria imaginaria, que se asigna a la memoria real, que podría almacenarse en una de varias ubicaciones reales. Además, tenga en cuenta que un puntero no tiene un “tamaño”. Siempre apunta al inicio de un poco de memoria asignada y depende de usted averiguar cuántos bytes incluir en la definición de una variable (por ejemplo, en C ++, una cadena o matriz de caracteres puede ser arbitrariamente larga , así que debes tener mucho cuidado para mantener ese conocimiento).
¿Qué puede hacer con el puntero que acaba de imprimir? No mucho en realidad. Dado que la ubicación del puntero cambiará de una ejecución a otra, tiene poco sentido anotarlo (excepto tal vez para calcular la distancia entre puntos en la memoria durante una sola ejecución de su aplicación). Lo más importante que podría hacer con un puntero sin formato sería conectarlo a un depurador para ver los datos sin procesar almacenados en esa ubicación, pero la mayoría de los depuradores de hoy en día son depuradores “simbólicos”, por lo que saben sobre el idioma (o idiomas) que se utilizan y, por lo tanto, puede hacer suposiciones informadas sobre la “longitud” de la variable que se está almacenando, evitando así tener que lidiar con los punteros sin procesar o los datos sin procesar, o con averiguar cuántos bytes mirar (sin mencionar los problemas de big-endian vs little-endian).