in

Comprender el calificador «volátil» en C | Conjunto 2 (ejemplos)

gfg 200x200 min

La palabra clave volatile está destinada a evitar que el compilador aplique optimizaciones en objetos que pueden cambiar de formas que el compilador no puede determinar.

Los objetos declarados como volátiles se omiten de la optimización porque sus valores pueden ser cambiados por código fuera del alcance del código actual en cualquier momento. El sistema siempre lee el valor actual de un objeto volátil desde la ubicación de la memoria en lugar de mantener su valor en un registro temporal en el punto en el que se solicita, incluso si una instrucción previa solicitó un valor del mismo objeto. Entonces, la pregunta simple es, ¿cómo puede cambiar el valor de una variable de tal manera que el compilador no pueda predecir? Considere los siguientes casos para responder a esta pregunta.

1) Variables globales modificadas por una rutina de servicio de interrupción fuera del alcance: Por ejemplo, una variable global puede representar un puerto de datos (normalmente un puntero global denominado IO mapeado en memoria) que se actualizará dinámicamente. El puerto de datos de lectura de código debe declararse como volátil para obtener los últimos datos disponibles en el puerto. Si no declara la variable como volátil, el compilador optimizará el código de tal manera que leerá el puerto solo una vez y seguirá usando el mismo valor en un registro temporal para acelerar el programa (optimización de velocidad). En general, un ISR se utiliza para actualizar estos puertos de datos cuando hay una interrupción debido a la disponibilidad de nuevos datos.

2) Variables globales dentro de una aplicación multiproceso: Hay varias formas de comunicación de subprocesos, visualización, transmisión de mensajes, memoria compartida, buzones de correo, etc. Una variable global es una forma débil de memoria compartida. Cuando dos subprocesos comparten información a través de una variable global, deben calificarse como volátiles. Dado que los subprocesos se ejecutan de forma asincrónica, cualquier actualización de la variable global debida a un subproceso debe ser recuperada recientemente por otro subproceso de consumidor. El compilador puede leer la variable global y colocarla en la variable temporal del contexto del hilo actual. Para anular el efecto de las optimizaciones del compilador, estas variables globales deben calificarse como volátiles.

Si no usamos un calificador volátil, pueden surgir los siguientes problemas
1) Es posible que el código no funcione como se esperaba cuando la optimización está activada.
2) Es posible que el código no funcione como se esperaba cuando las interrupciones están habilitadas y utilizadas.

Veamos un ejemplo para entender cómo los compiladores interpretan las palabras clave volátiles. Considere el siguiente código, estamos cambiando el valor del objeto const usando un puntero y estamos compilando código sin la opción de optimización. Por lo tanto, el compilador no realizará ninguna optimización y cambiará el valor del objeto const.

C

#include <stdio.h>

int main(void)

{

    const int local = 10;

    int *ptr = (int*) &local;

    printf("Initial value of local : %d n", local);

    *ptr = 100;

    printf("Modified value of local: %d n", local);

    return 0;

}

Cuando compilamos código con la opción «–save-temps» de gcc, genera 3 archivos de salida
1) código preprocesado (con extensión .i)
2) código de ensamblaje (con extensión .s) y
3) código objeto (con opción .o).

Compilamos código sin optimización, por eso el tamaño del código ensamblador será mayor (que se resalta en color rojo a continuación).

Producción:

  [[email protected]]$ gcc volatile.c -o volatile –save-temps
  [[email protected]]$ ./volatile
  Initial value of local : 10
  Modified value of local: 100
  [[email protected]]$ ls -l volatile.s
  -rw-r–r– 1 narendra narendra 731 2016-11-19 16:19 volatile.s
  [[email protected]]$

Compilemos el mismo código con la opción de optimización (es decir, la opción -O). En el siguiente código, «local» se declara como constante (y no volátil), el compilador GCC realiza la optimización e ignora las instrucciones que intentan cambiar el valor del objeto const. Por lo tanto, el valor del objeto constante sigue siendo el mismo.

C

#include <stdio.h>

int main(void)

{

    const int local = 10;

    int *ptr = (int*) &local;

    printf("Initial value of local : %d n", local);

    *ptr = 100;

    printf("Modified value of local: %d n", local);

    return 0;

}

Para el código anterior, el compilador realiza la optimización, por eso se reducirá el tamaño del código ensamblador.
Producción:

  [[email protected]]$ gcc -O3 volatile.c -o volatile –save-temps
  [[email protected]]$ ./volatile
  Initial value of local : 10
  Modified value of local: 10
  [[email protected]]$ ls -l volatile.s
  -rw-r–r– 1 narendra narendra 626 2016-11-19 16:21 volatile.s

Declaremos el objeto const como volátil y compilemos el código con la opción de optimización. Aunque compilamos código con la opción de optimización, el valor del objeto const cambiará, porque la variable se declara como volátil, lo que significa que no se realiza ninguna optimización.

C

#include <stdio.h>

int main(void)

{

    const volatile int local = 10;

    int *ptr = (int*) &local;

    printf("Initial value of local : %d n", local);

    *ptr = 100;

    printf("Modified value of local: %d n", local);

    return 0;

}

Producción:

  [[email protected]]$ gcc -O3 volatile.c -o volatile –save-temp
  [[email protected]]$ ./volatile
  Initial value of local : 10
  Modified value of local: 100
  [[email protected]]$ ls -l volatile.s
  -rw-r–r– 1 narendra narendra 711 2016-11-19 16:22 volatile.s
  [[email protected]]$

El ejemplo anterior puede no ser un buen ejemplo práctico, el propósito era explicar cómo los compiladores interpretan las palabras clave volátiles. Como ejemplo práctico, piense en el sensor táctil de los teléfonos móviles. El sensor táctil de abstracción del controlador leerá la ubicación del toque y lo enviará a aplicaciones de nivel superior. El controlador en sí no debe modificar (const-ness) la ubicación de lectura y asegurarse de que lee la entrada táctil cada vez que se actualiza (volatile-ness). Dicho controlador debe leer la entrada del sensor táctil de manera constante y volátil.

Nota: Los códigos anteriores son específicos del compilador y es posible que no funcionen en todos los compiladores. El propósito de los ejemplos es hacer que los lectores comprendan el concepto.

Artículo relacionado :
Entender el calificador «volátil» en C | Conjunto 1 (Introducción)
Consulte los siguientes enlaces para obtener más detalles sobre la palabra clave volátil:
Volátil: el mejor amigo de un programador
No utilice volátiles como primitiva de sincronización
Este artículo fue compilado por “Narendra Kangralkar” y revisado por el equipo de GeeksforGeeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema discutido anteriormente.

Si desea aprender de los mejores videos seleccionados y problemas de práctica, consulte el Curso básico de C de Básico a Avanzado C.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

apple touch icon@2

sockets – ¿Qué significa «restablecimiento de conexión por pares»?

665px Coinsurance copay OOP

Coseguro vs copago: diferencia y comparación