The ‘C’ test. Part – VIII

Volatile
8. What does the keyword volatile mean? Give three different examples of its use.

A volatile variable is one that can change unexpectedly. Consequently, the compiler can make no assumptions about the value of the variable. In particular, the optimizer must be careful to reload the variable every time it is used instead of holding a copy in a register. Examples of volatile variables are:

  • Hardware registers in peripherals (for example, status registers)
  • Non-automatic variables referenced within an interrupt service routine
  • Variables shared by multiple tasks in a multi-threaded application

Candidates who don’t know the answer to this question aren’t hired. I consider this the most fundamental question that distinguishes between a C programmer and an embedded systems programmer. Embedded folks deal with hardware, interrupts, RTOSes, and the like. All of these require volatile variables. Failure to understand the concept of volatile will lead to disaster.

On the (dubious) assumption that the interviewee gets this question correct, I like to probe a little deeper to see if they really understand the full significance of volatile . In particular, I’ll ask them the following additional questions:

  • Can a parameter be both const and volatile ? Explain.
  • Can a pointer be volatile ? Explain.
  • What’s wrong with the following function?

int square(volatile int *ptr)
{
return *ptr * *ptr;
}

The answers are as follows:

  • Yes. An example is a read-only status register. It is volatile because it can change unexpectedly. It is const because the program should not attempt to modify it
  • Yes, although this is not very common. An example is when an interrupt service routine modifies a pointer to a buffer
  • This one is wicked. The intent of the code is to return the square of the value pointed to by *ptr . However, since *ptr points to a volatile parameter, the compiler will generate code that looks something like this:

int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}

Because it’s possible for the value of *ptr to change unexpectedly, it is possible for a and b to be different. Consequently, this code could return a number that is not a square! The correct way to code this is:

long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}