2012-03-29 14 views
57

volatile es decirle al compilador que no optimice la referencia, de modo que cada lectura/escritura no use el valor almacenado en el registro pero tenga acceso a la memoria real. Puedo entender que es útil para algunas variables comunes, pero no entiendo cómo afecta volatile a un puntero.¿Por qué es útil un puntero de punto a volátil, como "volatile int * p"?

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?

Respuesta

101

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 a la que apunta p haya 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 normal, cada vez que leo o escribo *p, el compilador sabe que el valor puede haber cambiado inesperadamente.

No es un caso más para un uso volatile int*: Si se declara un int como volatile, entonces no debe apuntar en él con un habitual 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 C ya no se acuerda de que la variable apuntado por ptr es volatile, por lo que puede almacenar en caché el valor de *p en un registro de forma incorrecta . De hecho, en C++, el código anterior es un error. En su lugar, usted 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 (o no! Debe) tratar de optimizar los accesos a través *ptr.

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

int* volatile ptr; 

Esto dice que el puntero sí es volatile, lo que significa que el compilador no debe tratar de almacenar en caché el puntero en la memoria o tratar de optimizar el valor del puntero porque el propio puntero pudieron conseguir reasignado por otra cosa (hardware, otro hilo, etc.) se pueden combinar estos juntos si desea obtener esta bestia:

volatile int* volatile ptr; 

esto dice que tanto el puntero y el pointee podrían conseguir cambiado de forma inesperada . El compilador no puede optimizar el puntero y no puede optimizar lo que se apunta.

Espero que esto ayude!

+0

Creo que quieres decir "NO debes señalarlo con un int * normal" – markgz

+0

@ markgz- ¡Vaya! Si eso es correcto. Fijo. – templatetypedef

+0

Creo que también es un error en C, pero los compiladores de C son menos propensos a quejarse sobre tipos no coincidentes. –

6

Este código volatile int *p = some_addr declara un puntero a volatile int. El puntero en sí no es volatile.

En el improbable caso de que se necesitaba el puntero a ser volátiles, así como el int, que tendría que utilizar:

volatile int * volatile p; 

no puedo pensar en una situación en la que tendría que utilizar ese .

+2

Ejemplo: I 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 se establece por el código principal, y tanto el puntero como los datos se leen más tarde. – Christoph

Cuestiones relacionadas