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
?
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 volatile
entonces 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 volatile
por 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 int
por 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 volatile
lo 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!
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.
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.