En el Item2 en la página 16, (Prefiere concursos, enumeraciones e inlines a #defines), Scott dice:
Además, aunque los buenos compiladores no reservarán almacenamiento para objetos constantes de tipos enteros ...
No entiendo esto Si defino un objeto const, por ejemplo
const int myval = 5;
entonces seguramente el compilador debe reservar algo de memoria (de tamaño int) para almacenar el valor 5?
¿O se almacenan los datos constantes de alguna manera especial?
Esto es más una cuestión de almacenamiento informático, supongo. Básicamente, ¿cómo almacena la computadora los objetos constantes para que no se guarde ningún almacenamiento?
c++
computer-science
usuario619818
fuente
fuente
storage of const object
la fuente de su pregunta tiene poco valor.Respuestas:
Una afirmación un poco más correcta sería que los compiladores no dejarían de lado la memoria de datos para objetos constantes de tipo entero: lo cambiarían por memoria de programa . No hay diferencia entre los dos bajo la arquitectura de Von Neumann, pero en otras arquitecturas, como Harvard, la distinción es bastante importante.
Para comprender completamente lo que está sucediendo, debe recordar cómo el lenguaje ensamblador carga los datos para su procesamiento. Hay dos formas fundamentales de cargar los datos: leer una memoria desde una ubicación específica (denominado modo de direccionamiento directo ) o establecer una constante especificada como parte de la instrucción en sí (denominado modo de direccionamiento inmediato ). Cuando el compilador ve una
const int x = 5
declaración seguida deint a = x+x
, tiene dos opciones:x
se hace referencia al, genere una instrucción de carga inmediata del valor 5En el primer caso, verá una lectura
x
en el registro del acumulador , una adición del valor en la ubicación dex
a acumulador y una tienda en la ubicación dea
. En el segundo caso, verá una carga inmediata de cinco, una suma inmediata de cinco, seguida de una tienda en la ubicación dea
. Algunos compiladores pueden darse cuenta de que está agregando una constante a sí mismo, a optimizara = x+x
ena = 10
, y generar una sola instrucción que almacena las diez de la ubicación dea
.fuente
No necesariamente. También puede decidir usar el valor bruto 5 en lugar del
myval
código compilado.La diferencia entre
#define MYVAL 5
yconst int myval = 5
es que, en el primer caso, el compilador no tiene elección, ya que el preprocesador ya reemplazó todas las mencionesMYVAL
en el código fuente5
cuando el compilador llega a ver el código fuente. Sin embargo, en el último caso, hay una opción. Para una compilación de depuración no optimizada, el compilador puede asignar explícitamente aconst int
, por lo que en el depurador podrá ver la constantemyval
, en lugar de solo el valor bruto 5.fuente
Lo que dice la cita no es del todo correcto.
Un buen compilador no reservará almacenamiento para variables de const estáticas . Si la variable const no es estática y está en el alcance del archivo, debe reservar almacenamiento porque la variable podría ser referenciada desde otra unidad de compilación. Con las optimizaciones de tiempo de enlace, el enlazador podría eliminar el almacenamiento y reescribir las instrucciones que hacen referencia a la variable si puede probar que el programa no genera un puntero a esa variable.
Una razón mucho mejor para usar en
const int
lugar de#define
es que los depuradores no "ven" las macros, por lo que no puede inspeccionar un#defined
valor d en el depurador.fuente
Robaré la primera oración de la respuesta de Péter Török pero elaboraré de manera diferente: no necesariamente. También puede decidir usar el valor bruto 5 en lugar del
myval
código compilado.Tratar
myval
como una variable regular al asignarle espacio en la memoria puede tener implicaciones de rendimiento que varían de minúsculas a severas dependiendo de la arquitectura y cómo maneja la memoria.Trabajando de esa manera, un compilador emitiría una instrucción que diga algo como "registro de carga R con lo que esté en la ubicación de memoria
myval
". La ubicación demyval
como un operando de la instrucción, por lo que proviene directamente del mismo bloque de datos que la instrucción misma. En las CPU modernas, este valor estará fácilmente disponible en el chip debido a la captación previa de instrucciones. Con la dirección en la mano, la CPU todavía tiene que sacar el valor de la memoria. Eso podría ir rápidamente si la ubicación está cerca en caché o no tan rápido si no lo está. La CPU no solo tiene que salirse del chip para obtener el valor, sino que podría obligarla a eliminar otros datos más útiles de la memoria caché que tendrán que ser devueltos más tarde. Cuando el programa se ejecuta en un sistema operativo que virtualiza la memoria, el acceso a esa ubicación puede causar un error de página, lo que puede provocar que el programa se suspenda hasta que la página requerida se introduzca en la RAM a través de E / S periféricas (p. Ej., Disco),Al cablear el valor constante en el código objeto, el compilador emitiría una instrucción como "cargar el registro R con el valor
5
". Al igual que la dirección de memoria descrita anteriormente,5
sería un operando para la instrucción y estaría disponible de la misma manera (es decir, captado previamente). Ahí es donde termina la similitud, porque la CPU ahora tiene todo lo que necesita para ponerla5
en el registro R y continuar con su negocio. Dado que las direcciones y los registros suelen ser del mismo tamaño, no hay diferencia en el número de bytes que ocupa la instrucción y la ejecución real se lleva a cabo con cero posibilidades de fallas en la caché y fallas de página que pueden ocurrir cuando pescas algo sin memoria.El compilador podría, como señaló Péter, asignar espacio y un símbolo para las
myval
compilaciones de depuración. No habría ningún daño al hacer esto y aún cablear su valor, ya que el valor sigue siendo el mismo, pase lo que pase y el símbolo realmente está ahí para que los humanos lo usemos en la depuración.Tenga en cuenta que esto solo se aplica a los valores que se pueden mantener en los registros, porque los registros son enteros por naturaleza. Otras constantes terminarán en la memoria.
fuente
El compilador sustituirá el número cinco siempre que se use la variable 'myval'.
fuente
El compilador puede considerar los valores constantes como operandos inmediatos. Los operandos inmediatos no requieren almacenamiento de datos. El compilador puede tratar:
lo mismo que
El valor 5 no se almacena en la memoria de datos, sino como parte de la secuencia de instrucciones.
El compilador debe reservar el almacenamiento de datos en los casos en que se pueda tomar la dirección del valor. Incluso en ese caso, el compilador seguirá utilizando operaciones inmediatas cuando se use el valor de myVal.
fuente