Can someone help me out here? This is one of those areas of C
that I am fuzzy on. I'm not quite sure when I should use volatile.
If you could provide an example, that would help out a lot.
I know it has to do with the expectation that the variable can be
changed outside of the control of the program. I know it has to
do with telling the compiler to not optimize that piece of code,
so that the variable can be changed from outside of the program.
Specifically, it tells the compiler that the very act of
accessing the volatile variable, for read or for write, may have
a necessary side-effect. The compiled code must actually perform
all the accesses implied by the abstract machine, and cannot
optimize them away or rearrange them w.r.t. sequence points.
A loop that polls a volatile device register until the READY bit
is set must actually read the register on each iteration; the
compiler cannot just fetch it once and then go into a tight loop
testing and re-testing the fetched value. A sequence of
assignments like
*device_register = DEVICE_RESET;
*device_register = DEVICE_SETMODE | 42;
*device_register = DEVICE_START;
cannot be replaced by the final assignment alone.
Unfortunately, there remains one gigantic non-portable hole in
the semantics of volatile: The compiled code must perform all the
accesses implied by the abstract machine, but the implementation
gets to define what an "access" is. Many uses of volatile thus
require intimacy with the implementation's documentation.
But I struggle with the thought process as to deciding when to
use it.
A strictly-conforming C program needs volatile in only one
circumstance (unless I've forgotten something ;-): when a function
that calls setjmp() wants to rely on the value of a local variable
that might be changed between setjmp() and longjmp(). Makeing such
a variable volatile "forces it to memory" whenever it's changed, and
forces it to be read from memory whenever it's inspected. Thus you
never get a value in a register becoming out-of-date with respect
to the value in memory when longjmp() messes up the normal flow
of control.
Other uses of volatile are connected with implementation-
specific goodies like asynchronous signals, memory locations that
do something other than passively store values (e.g., hardware
counters, I/O status and command registers), and other sorts of
"independent activity." (Not including multi-threaded programs,
by the way: volatile is neither necessary nor sufficient for data
that's shared between threads.)
If you're not using setjmp()/longjmp() and you're not using
asynchronous signals and special memory locations and the like,
you don't need (or want) volatile.
<OT>
I was reading the source code for ftp (the client), and I
see it used throughout. And I found myself second guessing
my understanding of its use.
</OT>
Keep in mind that the author of the code may have been as
uncertain about volatile as you are. Just because something has
been ritten doesn't mene its rite.