Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

c

What is the volatile type qualifier in C?

Hammad Nasir

Grokking Modern System Design Interview for Engineers & Managers

Ace your System Design Interview and take your career to the next level. Learn to handle the design of applications like Netflix, Quora, Facebook, Uber, and many more in a 45-min interview. Learn the RESHADED framework for architecting web-scale applications by determining requirements, constraints, and assumptions before diving into a step-by-step design process.

Answers Code

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 interrupta signal from a device or a program which requires the operating system to suspend the current task and deal with the interrupt first modifies a global variable
  • Another threada thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler in the program modifies a global variable

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 volatile type qualifier can come either before or after the datatype.

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, concurrent inputan input that does not halt the program from the user or a device is required. A signal from such a device (called an Interrupt) instructs the system to fulfill this requirement by feeding data directly into the variable’s location in the main memory without halting the program control flow. However, if the compiler has optimized the variable, its value is kept in and used from the register in the CPU as depicted in the figure below:

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;
}

RELATED TAGS

c

CONTRIBUTOR

Hammad Nasir
Copyright ©2022 Educative, Inc. All rights reserved

Grokking Modern System Design Interview for Engineers & Managers

Ace your System Design Interview and take your career to the next level. Learn to handle the design of applications like Netflix, Quora, Facebook, Uber, and many more in a 45-min interview. Learn the RESHADED framework for architecting web-scale applications by determining requirements, constraints, and assumptions before diving into a step-by-step design process.

Answers Code
Keep Exploring