Understanding Volatile Variable in C

As the name suggests, volatile specifier indicates the compiler that the value of the variable is volatile i.e. it can change unexpectedly. But, the question comes why do we need to even specify that a variable value is volatile.

The Requirement for volatile specifiers

Our compilers offer a set of options to perform a specified level of optimization onto the C-code written. However, even with the lowest optimization specified, compilers do a bare minimum optimization during compilation.

In the above method, mr. compiler observes that, we are assigning the received ‘time’ value into a separate variable and subtracting it from the same without doing any operation on the same.

Wise enough, compiler optimizes the second READ operation fo the variable ‘time’. That is, it sees that the value of ‘time’ does not change anyhwere in this single threaded program, hence avoids to read the value from the memory, second time during the return statement, making it returning a zero always. As for the compiler, the value in ‘time’ and ‘t1’ is same during the execution of method().

However, the programmer’s requirement and intention is to link the variable ‘time’ to a hardware counter which changes with every tick of the system clock. Basically, the programmer wanted to calculate the time taken by the program to compute the series. However, the compiler’s optimization entirely changed the programmer’s intended behavior.

The solution is the ‘volatile’ specifier. A volatile variable indicates mr. compiler not to optimize the variable as it’s value might change, not visible in the scope of the visible source code.

Have a look at the usage of volatile specifier for the above example code while calling:

Example

In the above source code, the programmer wants to observe a LED’s on and offs for a span of 1 minute. The variable v1 is allocated a register which is taking its value from a LED switch. That is, turning on the LED sends a signal to write ‘1’ to the register and turning off writes ‘0’ to the register. Therefore, in case the variable ‘v1’ is not declared volatile, mr. compiler would perceive following conditional statement as false always.

Code:

if(v1 == 0)

Reason being, during the control flow of the source, compiler does not see the value of v1 changing anywhere. Hence, it would like to avoid the ‘READ v1’ and optimize the condition to false. Making it volatile tells the compiler, the its value can be modified unexpectedly and hence it should make sure to read its value from the register everytime it is accessed.

When to use volatile specifiers

Now, it is clear, that volatile variable forces the compiler to cease optimizations. Hence, we should be really careful using it in our programs. There can be two major use cases for volatile variables to be used:-

In case of memory mapped hardware related programs. That is, where peripheral, ports, co-processor memories are mapped into the program’s memory. Generally, register LOAD’s and STORE’s are efficient than memory reads and writes. Hence, compiler always tries to avoid and optimize any redundant memory reads in case the value is already in the register. Such kind of optimization to reduce any redundant LOAD-STORE can be halted through volatile variables.

In case of shared memory between two programs. Generally, programmers use shared memories to communicate, thereby changing the value in one program and accessing it in the other. However, unless it is explicitly specified as a volatile variable, the compiler can optimize it unknowingly it can be modified by the other program. Volatile variables come to rescue in such scenarios.

Conclusion

I hope now we all understand the basic idea behind volatile variables and where it makes sense to use them. Generally volatile specifiers are more helpful during low level programming e.g device drivers etc. Hence, as a caveat, be very sure about its usage before you actually use it in your implementation.