volatile tells the compiler that the variable may be changed by a machanism outside the programs flow of control.
So for example if I had a variable which was located by the linker in a memory location that was really a hardware status register then the hardware can change the value of that variable at any time.
if I declare the variable to be volatile and write :
volatile int status;
.
.
.
while (status & 0xE0) {};
the code will spin until the relevant bit is set (this is a very common thing to do when waiting for hardware to become ready in embedded systems).
Without the volatile, the compiler will optimise the loop possibly to either
while (1) {}; or even while (0){};
Which is not the same thing at all!
You can think of a volatile decaration as "Do not optimise accesses to this", the semantics are actually somewhat more subtle, but this gets the basic idea across.
HTH.
Regards, Dan.