What is the volatile type qualifier in C?
The need for the volatile type qualifier
Compilers apply several optimizations to increase the run time performance of the program or to keep the size of the executable file minimal. One such optimization is to structure the executable code so that the values of some variables are stored inside the temporary registers in the CPU for most of the program’s lifecycle. Even though temporary registers can be accessed faster than the main memory (RAM), this can lead to unusual behavior in the following cases:
- An
modifies a global variableinterrupt a signal from a device or a program which requires the operating system to suspend the current task and deal with the interrupt first - Another
in the program modifies a global variablethread a thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler
The volatile keyword is used to prevent these optimizations of a variable.
The volatile type qualifier
The volatile type qualifier instructs the compiler to not apply optimizations on a variable and has the following structure:
volatile datatype identifier;
datatype volatile identifier;
Note: The
volatiletype qualifier can come either before or after thedatatype.
Use cases of the volatile type qualifier
The following examples discuss the issues that arise due to compiler optimization and how the volatile type qualifier resolves them:
An interrupt modifies a global variable
In some programs,
Since the program never actually reads the global variable’s value from the RAM, it never utilizes the data sent from the input device.
Another thread in the program modifies a global variable
A thread in a computer program is a sequence of tasks that can run concurrently with other threads. A program may run more than one thread, which can read from or write to the same global variable. In this situation, if the compiler optimizes this global variable, the updates made by one thread will not be fetched by another thread, leading to unexpected program behavior.
Example usage of the volatile type qualifier
The code below initializes a constant integer variable x to the value 1. Then, an integer pointer p points to the same location as x (allowing us to modify x using p). The value of x is modified using the pointer p and the value of x before and after modification is printed:
#include <iostream>using namespace std;int main() {const int x = 1;int * p = (int*) &x;cout << "Value of x before modification: " << x << endl;*p = 99;cout << "Value of x after modification: " << x << endl;return 0;}
Surprisingly, the value of x before and after modification comes out to be 1. The reason is that the compiler optimizes the variable x by keeping its value in a temporary register throughout the lifecycle of the program. Even though the pointer p changed the value of x to 99 in the RAM, the program never accessed that value.
On the contrary, if we use the volatile type classifier with the variable x, the value before modification comes out to be 1 and the value after modification comes out to be 99. The example code is as follows:
#include <iostream>using namespace std;int main() {const volatile int x = 1;int * p = (int*) &x;cout << "Value of x before modification: " << x << endl;*p = 99;cout << "Value of x after modification: " << x << endl;return 0;}
Free Resources