¿Qué significa declarar una variable volátil?

9

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?

Vikaton
fuente
1
Si está leyendo su edad en una volatilevariable y dice 5, y la vuelve a leer el próximo año, tiene garantizado que obtendrá 6.
5gon12eder
@ 5gon12eder, entiendo que volátil significa que algo está sujeto a cambios rápidos y fáciles, pero ¿cómo funciona? : S
Vikaton
Además, dependiendo de sus indicadores de compilación, una variable no volátil 'podría' aparecer en su depurador (digamos que está usando código C + Eclipse + gdb por ejemplo), como: 'valor optimizado' porque el valor de la variable ahora es en algún lugar de un registro. Si no sabe cómo usar las herramientas / características de depuración en lenguaje ensamblador, simplemente declare su variable usando el modificador volátil.

Respuestas:

11

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 5desde una variable y no la cambias, seguirá conteniendo 5. 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 el 5.

Pero podría leerlo como 5, entonces quizás el sistema carga datos del disco en esa memoria, cambiándolo a 500. Si desea que su programa lea el nuevo valor 500, necesita que el compilador no sea demasiado inteligente sobre el uso de la lectura anterior 5. Debe decirle que vuelva a cargar el valor cada vez. Eso es lo que volatilehace.

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 borra 3 to 4y escribe 3 to 5.

Cuando vayas a poner el puntaje del juego en tu historia, podrías:

  1. Escriba el último puntaje que leyó, 3 to 4asumiendo alegremente que no cambió (o no le importa si lo hizo), o
  2. Camine hacia el lado opuesto de la tabla para leer la puntuación actual (que 3 to 5ahora es ahora) y retroceda. Así es como volatileactúa una variable.
Jerry101
fuente
11

volatile significa dos cosas:

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

  2. 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:

i = 2; 
i = i; 

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 setjmpy luego longjmpse 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.

gnasher729
fuente
Hay algunos problemas sutiles aquí. Un problema sutil es que has caracterizado las lecturas volátiles como una característica de la variable cuando en realidad son una característica de cómo se accede a la variable . Si tenemos la variable iy el valor pi = &i, entonces x = *pileemos i, pero no se garantiza que esa lectura tenga una semántica volátil.
Eric Lippert el
1
@EricLippert: Si ise declara como volatile int ise pidebe declarar como volatile int *pi, en cuyo caso *pies un acceso volátil, ¿no?
Jon Purdy
2

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 primero statement_Aen su totalidad, luego statement_B, y finalmente statement_C. La implementación no puede recordar que asignó ageel valor de 5. Cada declaración que hace referencia agedebe acceder al valor de esa variable.

No habría necesidad de la volatilepalabra 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-ifregla, la secuencia statement_A; statement_B; statement_C;podría implementarse ejecutando parte de statement_C, luego parte de statement_A, luego todo statement_B, luego el resto statement_Ay finalmente el resto statement_C.

Esas reglas como si no se aplican a las volatilevariables. Con respecto a las volatilevariables 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

¿Qué significa cuando el compilador no "optimiza" la dirección de memoria?

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

David Hammen
fuente
1

(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):

  • no volátil significa que su compilador actual decide dónde se ubicará la variable o cómo se transfiere el valor de la variable a una subrutina
    • en una dirección de memoria fija,
    • en la pila [en relación con el puntero de pila actual de los procesadores],
    • en el montón [en relación con el puntero base actual del procesador],
    • en un registro de procesador,
    • ...
  • volátil significa que el compilador no puede optimizar la variable porque algo más fuera del control main-cpu-s (es decir, un ioprocesador separado) puede cambiar este valor.
k3b
fuente
0

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.

viejo contador de tiempo
fuente