The main intended use-case for
volatile in C and C++ is to access data that can be modified by something external to the program,
typically some hardware register. In contrast with other languages that provide a
volatile keyword, it does not provide any useful
guarantees related to atomicity, memory ordering, or inter-thread synchronization. It is only really needed for the kind of low-level code found in
kernels or embedded software, i.e. using memory-mapped I/O registers to manipulate hardware directly.
According to the C standard:
volatile is a hint to the implementation to avoid aggressive optimization involving the object because the value of the object might
be changed by means undetectable by an implementation.
Only C11/C++11 "atomic types" are free from data races, and you should use them or synchronization primitives if you want to avoid race
This rule raises an issue when a local variable or class data member is declared as
volatile (at the top level of the type, pointers
to volatile are not reported).
Noncompliant Code Example
volatile int counter; // Noncompliant
User * volatile vpUser; // Noncompliant; pointer is volatile
User volatile * pvUser; // Compliant; User instance is volatile, not the pointer
User volatile * pvUser;