volatile
The syntax of volatile
is identical to that for const, but
volatile means “This data may change outside the knowledge of the
compiler.” Somehow, the environment is changing the data (possibly through
multitasking, multithreading or interrupts), and volatile tells the
compiler not to make any assumptions about that data, especially during
optimization.
If the compiler says, “I read this
data into a register earlier, and I haven’t touched that register,”
normally it wouldn’t need to read the data again. But if the data is
volatile, the compiler cannot make such an assumption because the data
may have been changed by another process,
and it must reread that data
rather than optimizing the code to remove what would normally be a redundant
read.
You create volatile objects using
the same syntax that you use to create const objects. You can also create
const volatile objects, which can’t be changed by the client
programmer but instead change through some outside agency. Here is an example
that might represent a class associated with some piece of communication
hardware:
//: 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
} ///:~
As with const, you can use
volatile for data members, member functions, and objects themselves. You
can only call volatile member functions for volatile
objects.
The reason that isr( )
can’t actually be used as an interrupt service routine
is that in a member function, the address of the current
object (this) must be secretly passed, and an ISR generally wants no
arguments at all. To solve this problem, you can make isr( ) a
static member
function,
a subject covered in Chapter 10.
The syntax of volatile is
identical to const, so discussions of the two are often treated together.
The two are referred to in combination as the c-v
qualifier.