Muchos programas de bajo nivel utilizan la palabra clave volátil para los tipos de mapeo de memoria y demás, sin embargo, estoy un poco confundido sobre lo que REALMENTE hace en segundo plano. En otras palabras, ¿qué significa que el compilador no "optimice" la dirección de memoria?
9
volatile
variable y dice 5, y la vuelve a leer el próximo año, tiene garantizado que obtendrá 6.Respuestas:
volatile
significa que algún otro procesador o dispositivo de E / S o algo puede cambiar la variable debajo de ti.Con una variable ordinaria, los pasos de su programa son lo único que lo cambiará. Entonces, por ejemplo, si lees
5
desde una variable y no la cambias, seguirá conteniendo5
. Como puede confiar en eso, su programa no tiene que tomarse el tiempo de leer la variable nuevamente la próxima vez que quiera usarla. El compilador de C ++ es inteligente para generar código que solo recuerda el5
.Pero podría leerlo como
5
, entonces quizás el sistema carga datos del disco en esa memoria, cambiándolo a500
. Si desea que su programa lea el nuevo valor500
, necesita que el compilador no sea demasiado inteligente sobre el uso de la lectura anterior5
. Debe decirle que vuelva a cargar el valor cada vez. Eso es lo quevolatile
hace.Una analogía para niños de 5 años
Digamos que pones una gran hoja de papel sobre una mesa. En una esquina del papel, anotar la puntuación actual de un juego en curso,
3 to 4
. Luego vas al lado opuesto de la mesa y empiezas a escribir una historia sobre el juego. Tu amigo que está viendo el juego actualiza la puntuación en esa esquina a medida que avanza el juego. Ella borra3 to 4
y escribe3 to 5
.Cuando vayas a poner el puntaje del juego en tu historia, podrías:
3 to 4
asumiendo alegremente que no cambió (o no le importa si lo hizo), o3 to 5
ahora es ahora) y retroceda. Así es comovolatile
actúa una variable.fuente
volatile
significa dos cosas:El valor de la variable puede cambiar sin que ningún código suyo lo cambie. Por lo tanto, cada vez que el compilador lee el valor de la variable, es posible que no asuma que es igual a la última vez que se leyó, o que es el mismo que el último valor almacenado, pero debe leerse nuevamente.
El acto de almacenar un valor en una variable volátil es un "efecto secundario" que se puede observar desde el exterior, por lo que el compilador no puede eliminar el acto de almacenar un valor; por ejemplo, si dos valores se almacenan en una fila, el compilador debe almacenar el valor dos veces.
Como ejemplo:
El compilador debe almacenar el número dos, leer la variable i, almacenar la variable que leyó en i.
Existe otra situación: si una función usa
setjmp
y luegolongjmp
se llama, se garantiza que todas las variables locales volátiles de la función tienen el último valor almacenado; este no es el caso con las variables locales no volátiles.fuente
i
y el valorpi = &i
, entoncesx = *pi
leemosi
, pero no se garantiza que esa lectura tenga una semántica volátil.i
se declara comovolatile int i
sepi
debe declarar comovolatile int *pi
, en cuyo caso*pi
es un acceso volátil, ¿no?Explicación abstracta
Tanto C como C ++ tienen un concepto de máquina abstracta . Cuando el código usa el valor de alguna variable, la máquina abstracta dice que la implementación tiene que acceder al valor de esa variable. El código del formulario
statement_A; statement_B; statement_C;
debe ejecutarse exactamente en el orden especificado. Las expresiones comunes a esas tres declaraciones deben ser recalculadas cada vez que ocurren.Según las máquinas abstractas, dada la secuencia de enunciados
statement_A; statement_B; statement_C;
, la implementación debe realizarse primerostatement_A
en su totalidad, luegostatement_B
, y finalmentestatement_C
. La implementación no puede recordar que asignóage
el valor de 5. Cada declaración que hace referenciaage
debe acceder al valor de esa variable.No habría necesidad de la
volatile
palabra clave si las implementaciones ejecutaran estrictamente el código C o C ++ según las especificaciones de la máquina abstracta. Las máquinas abstractas C y C ++ no tienen un concepto de registros, ningún concepto de subexpresiones comunes, y el orden de ejecución es estricto.Ambos idiomas también tienen reglas como si . Una implementación cumple con el estándar siempre que esa implementación se comporte como si hubiera ejecutado cosas según la especificación de máquina abstracta. El compilador puede asumir que las variables no volátiles no cambian los valores entre asignaciones. Mientras no rompa la
as-if
regla, la secuenciastatement_A; statement_B; statement_C;
podría implementarse ejecutando parte destatement_C
, luego parte destatement_A
, luego todostatement_B
, luego el restostatement_A
y finalmente el restostatement_C
.Esas reglas como si no se aplican a las
volatile
variables. Con respecto a lasvolatile
variables y funciones, una implementación tiene que hacer exactamente lo que le dijo que hiciera, y exactamente en el orden en que le dijo que hiciera las cosas.Hay una desventaja en la especificación de la máquina abstracta: es lenta. Un aspecto positivo de C y C ++ en comparación con otros lenguajes es que son bastante rápidos. Este no sería el caso si el código se ejecutara por estas máquinas abstractas. Las reglas as-if son las que permiten que C y C ++ sean tan rápidos.
Respuesta ELI5
"Optimizar" una dirección de memoria es un concepto avanzado, algo que no está dentro del alcance de las capacidades de un niño de cinco años. Los niños de cinco años que cumplen con las normas harán exactamente lo que usted les diga, ni más ni menos. Con
volatile
, le está diciendo a la implementación que actúe como si fueran cinco: sin pensar, sin optimizaciones elegantes. En cambio, la implementación tiene que hacer exactamente lo que el código le dice que haga.fuente
(no) volátil es una pista para el compilador de cómo optimizar el código (desde el punto de vista del código de ensamblaje generado):
fuente
Las respuestas parecen bastante consistentes pero pierden un punto importante. Le está diciendo al compilador que desea asignar espacio y para cada acceso, leer O ESCRIBIR, desea que realice ese acceso. No queremos que optimice esos accesos o esa variable por alguna razón.
Sí, una razón es porque alguien más podría cambiar ese valor para nosotros. Otra razón es que podríamos estar cambiando ese valor para otra persona. Que alguien más sea el que lo cambia por nosotros o el que lo estamos cambiando podría ser hardware / lógica o software. A menudo se usa para definir los accesos a los registros de control y estado en programas integrados de metal desnudo, escribiendo o leyendo desde el hardware. Además del software que habla con el software explicado en otras respuestas.
También verá volátiles utilizados para controlar cuándo y en qué orden ocurren los accesos, si está tratando de cronometrar una sección de código, y no usa volátiles, las variables en cuestión (hora de inicio, hora de finalización y diferencia) solo necesitan ser calculado cerca del final, el compilador es libre de mover cualquiera de las mediciones de tiempo (no donde las colocamos), no es que no sea volátil, pero la experiencia lo demuestra menos probable.
En ocasiones, verá que solía simplemente quemar el tiempo, un intermitente led elemental, el hola mundo del metal desnudo, podría usar un volátil para una variable que cuenta en un gran número solo para quemar el tiempo para que el ojo humano vea el led cambian de estado. Ejemplos más avanzados que usar temporizadores u otros eventos para quemar el tiempo.
fuente