Volatile in C


Reading time: 30 minutes | Coding time: 5 minutes

Volatile in C programming language is a keyword which is used with variables to inform the compiler not to apply any optimizations to code dealing with the variable. This is used to avoid some assumptions that go into compiler optimizations which can break the code. This is mainly used in Embedded Systems programming and real time systems.

Syntax:

volatile <data_type> <variable_name>;
// or
<data_type> volatile <variable_name>;

Example:

volatile int opengenus = 1;

As a general rule, all variables whose value can change suddenly due to an external reason (like an external device or another program thread) should be declared using volatile.

Note that unnecessarily using volatile for all keywords will reduce performance and not using it when required will result in unexpected execution result.

Compiler optimizations include:

  • caching variables
  • skip checking loop termination conditions or doing it at compile time only
  • pre-determining the conditional program path

and many more. Volatile is the approach to keep the perfect balance between program correctness and performance.

Simple example

To understand the importance of volatile in C, let us consider a simple example (main.c) as below:

#include "opengenus_header.h"

int main()
{
    while(opengenus) {}; // infinite loop
}

We will have a header file opengenus_header.h as:

extern int opengenus;

We will have a common file named og.c to declare opengenus variable as:

#include "opengenus_header.h"

int opengenus = 1;

Now, if we compile and execute main.c by linking it with og.c, it will fall into an infinite loop.

gcc main.c og.c
./a.out

This is only because of compiler optimizations.

Our compiler (GNU GCC) will think intelligently and see that the value of opengenus variable is 1 and will avoid all other checks for the while loop and get into an infinite loop.

The problem is that the value of opengenus variable can get changed inbetween and this will allow the while loop to break but as the compiler has optimized the code to check the value of opengenus variable only once and at the beginning, it will never reach the condition to get out of the loop.

To prevent this, there are two options:

  • turn off all compiler optimizations
  • turn off compiler optimizations only for required code sections

Turning off all compiler optimizations will greatly impact the overall performance and hence, the better approach is to turn off optimizations for specific code sections. This is done using volatile keyword.

To solve this, we need to modify og.c as:

#include "opengenus_header.h"

volatile int opengenus = 1;

Now, if we execute another thread in parallel to modify the value of opengenus variable to 0, the while loop will be stopped.

Real life use of volatile

Variables should be declared volatile if its value can be changed asynchronously. Such situations include:

  • variables representing device or peripheral registers. Devices can get disconnected or damaged anytime.
  • variables whose value is changed by a system call like interrupt service routine
  • global variables
  • program is not thread safe
  • variables which are accessed in multiple threads

Note that volatile should not be used as a synchronization method.