La sintaxis de volatile
es idéntica a la de
const
, pero volatile
significa «este
dato puede cambiar sin que el compilador sea informado de
ello». De algún modo, el entorno modifica el dato
(posiblemente mediante multitarea, multihilo o interrupciones),
y volatile
indica la compilador que no haga
suposiciones sobre el dato, especialmente durante la
optimización.
Si el compilador dice, «yo guardé este dato en un registro
anteriormente, y no he tocado ese registro», normalmente
no necesitará leer el dato de nuevo desde memoria. Pero si esa
variable es volatile
, el compilador no debe hacer esa
suposición porque el dato puede haber cambiado a causa de otro
proceso, y debe releer el dato en vez de optimizar el código
(dicha optimización consiste en eliminar la lectura redundante
que se hace normalmente).
Pueden crearse objetos volatile
usando la misma
sintaxis que se usa para crear objetos constantes. También puede
crearse objetos volatile
constantes que no pueden
cambiarse por el programador cliente pero se pueden modificar
por una entidad ajena al programa. Aquí se muestra un ejemplo
que representa una clase asociada con algún elemento físico de
comunicación.
//: C08:Volatile.cpp // The volatile keyword class Comm { const volatile unsigned char byte; volatile unsigned char flag; enum { bufsize = 100 }; unsigned char buf[bufsize]; int index; public: Comm(); void isr() volatile; char read(int index) const; }; Comm::Comm() : index(0), byte(0), flag(0) {} // Only a demo; won't actually work // as an interrupt service routine: void Comm::isr() volatile { flag = 0; buf[index++] = byte; // Wrap to beginning of buffer: if(index >= bufsize) index = 0; } char Comm::read(int index) const { if(index < 0 || index >= bufsize) return 0; return buf[index]; } int main() { volatile Comm Port; Port.isr(); // OK //! Port.read(0); // Error, read() not volatile } ///:~
Listado 8.18. C08/Volatile.cpp
Como ocurre con const
, se puede usar volatile
para los atributos de la clase, los métodos y para los objetos
en sí mismos. Sólo puede llamar a métodos volatile
desde objetos volatile
.
La razón por la que isr()
no se puede usar
como una rutina de servicio de interrupción (ISR) es que en un
método, la dirección del objeto actual (this
)
debe pasarse secretamente, y una ISR no requiere
argumentos. Para resolver este problema se puede hacer que el
método isr()
sea un método de clase
(static
), un asunto que se trata en el [FIXME:capitulo
10].
La sintaxis de volatile
es idéntica a la de
const
, así que por eso se suelen tratar juntos. Cuando
se usan combinados se conocen como cuantificador
c-v (const-volatile).