¿Por qué es útil un puntero de punto a volátil, como “volatile int * p”?

4 minutos de lectura

avatar de usuario
Infinito

volatile es decirle al compilador que no optimice la referencia, de modo que cada lectura/escritura no use el valor almacenado en el registro sino que haga un acceso real a la memoria. Puedo entender que es útil para alguna variable ordinaria, pero no entiendo cómo volatile afecta a un puntero.

volatile int *p = some_addr;
int a = *p; // CPU always has to load the address, then does a memory access anyway, right?

¿Cuál es la diferencia si ha sido declarado como int *p = some_addr?

avatar de usuario
templatetypedef

Un puntero de la forma

volatile int* p;

es un puntero a un int que el compilador tratará como volatile. Esto significa que el compilador supondrá que es posible que la variable que p apunta a haber cambiado incluso si no hay nada en el código fuente que sugiera que esto podría ocurrir. Por ejemplo, si configuro p para apuntar a un entero regular, entonces cada vez que leo o escribo *p el compilador sabe que el valor puede haber cambiado inesperadamente.

Hay un caso de uso más para un volatile int*: Si declara un int como volatileentonces no deberías señalarlo con un int*. Por ejemplo, esta es una mala idea:

volatile int myVolatileInt;
int* ptr = &myVolatileInt; // Bad idea!

La razón de esto es que el compilador de C ya no recuerda que la variable señalada por ptr es volatilepor lo que podría almacenar en caché el valor de *ptr en un registro incorrectamente. De hecho, en C++, el código anterior es un error. En su lugar, debe escribir:

volatile int myVolatileInt;
volatile int* ptr = &myVolatileInt; // Much better!

Ahora, el compilador recuerda que ptr puntos en un volatile intpor lo que no intentará (¡o no debería!) optimizar los accesos a través de *ptr.

Un último detalle: el puntero que discutió es un puntero a un volatile int. También puedes hacer esto:

int* volatile ptr;

Esto dice que el puntero sí mismo es volatilelo que significa que el compilador no debe tratar de almacenar en caché el puntero en la memoria ni intentar optimizar el valor del puntero porque el puntero en sí podría ser reasignado por otra cosa (hardware, etc.). Puede combinarlos si lo desea. consigue esta bestia:

volatile int* volatile ptr;

Esto dice que tanto el puntero como el apuntado podrían cambiar inesperadamente. El compilador no puede optimizar el puntero en sí mismo, y no puede optimizar lo que se apunta.

¡Espero que esto ayude!

  • Creo que quieres decir “NO debes señalarlo con un int regular *”

    – markgz

    29 de marzo de 2012 a las 23:52

  • Creo que también es un error en C, pero los compiladores de C son menos propensos a quejarse de las discrepancias de tipo.

    – Chris Lutz

    29 de marzo de 2012 a las 23:53

  • Gracias. Entonces, no hay diferencia si hay “volátil” para mi ejemplo, ¿verdad? Pero si hay otra declaración “int b = *p” a continuación, hace una diferencia, ¿verdad? Específicamente, “b” puede inicializarse usando un registro que almacena “*p” en lugar de hacer una referencia de memoria real.

    – Infinito

    29 de marzo de 2012 a las 23:55

  • @SetTimer- Eso realmente depende de qué do_something_else es. Si el compilador pudiera estar completamente convencido de que do_something_else Nunca cambió el valor de xentonces definitivamente podría leer el valor de *p fuera de un registro si quisiera. Dudo que para cualquier código razonable y la mayoría de los compiladores esto realmente suceda, pero en teoría sería posible. ¿Tiene sentido?

    – templatetypedef

    30 de marzo de 2012 a las 0:16

  • Resumen del informe de defectos de @olaf para la versión 1.10 de C11 Fecha: abril de 2016 DR 476 semántica volátil para lvalues 04/2016 Abierto

    – filipina

    19 de febrero de 2017 a las 2:07

este codigo volatile int *p = some_addr declara un puntero a un volatile int. El puntero en sí no es volatile.

En el improbable caso de que necesitara que el puntero fuera volátil al igual que el int, necesitaría usar:

volatile int * volatile p;

No puedo pensar en una situación en la que necesites usar eso.

  • Ejemplo: estoy usando ‘volatile uint8_t* volatile pData’ en el código ISR que modifica el puntero y los datos a los que apunta. El puntero lo establece el código principal, y tanto el puntero como los datos se leen más tarde.

    – Cristóbal

    24 de febrero de 2013 a las 0:24

Sobre la utilidad de volátil: esto es necesario, si necesita verificar la memoria, que es modificada por hardware como un controlador de interfaz en serie. Tiene su aplicación en el mundo de los sistemas embebidos, donde trabajas muy cerca del hardware sin ningún SO de por medio.

  • O si está desarrollando el sistema operativo.

    – Atilla Filiz

    21 de junio de 2019 a las 8:24

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad