Difference between revisions of "Volatile Variable"
Proj user14 (talk | contribs) |
|||
(2 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
− | This famous '''volatile''' variable article... Reading this article might just find you a job because C/C++ interviews tend to have this very common question on the list! | + | This famous '''volatile''' variable article... Reading this article might just find you a job because C/C++ interviews tend to have this very common question on the list! The textbook definition of a volatile variable is: |
− | |||
− | The textbook definition of a volatile variable is: | ||
"Any variable that is subject to change externally should be declared volatile". | "Any variable that is subject to change externally should be declared volatile". | ||
− | This often doesn't click in people's mind on what the '''volatile''' keyword actually does. It has to do with the way CPUs work and the way compilers optimize your programs. Let's assume that you are compiling in GCC with optimizations turned on and | + | This often doesn't click in people's mind on what the '''volatile''' keyword actually does. It has to do with the way CPUs work and the way compilers optimize your programs. Let's assume that you are compiling in GCC with optimizations turned on and you're working on a loop until a certain bit is set : |
+ | <BR/> | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
// Assume you have a CPU register called UART_STATUS | // Assume you have a CPU register called UART_STATUS | ||
Line 12: | Line 11: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | If UART_STATUS variable is not volatile, you've got a potential infinite loop even if the bit sets due to GCC optimization technique. Remember that CPUs have to bring information from MEMORY to REGISTERS and GCC may optimize your code such that MEMORY to REGISTER instruction is minimally used to enhance performance. | ||
− | |||
− | Assembly code without volatile: | + | '''Assembly code without volatile:''' |
<syntaxhighlight lang="asm"> | <syntaxhighlight lang="asm"> | ||
LOAD R0, &UART_STATUS | LOAD R0, &UART_STATUS | ||
Line 23: | Line 23: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Assembly code *with* volatile: | + | '''Assembly code *with* volatile:''' |
<syntaxhighlight lang="asm"> | <syntaxhighlight lang="asm"> | ||
LOOP: | LOOP: | ||
Line 33: | Line 33: | ||
<BR/> | <BR/> | ||
=== Compiler Optimization === | === Compiler Optimization === | ||
− | The compiler basically optimizes the loop taking for granted that the memory variable UART_STATUS is not changing INSIDE the loop, therefore, there is no need for a LOAD from memory | + | The compiler basically optimizes the loop taking for granted that the memory variable UART_STATUS is not changing INSIDE the loop, therefore, there is no need for a (re)LOAD from memory instruction inside the loop. Using volatile keyword in this case tells the compiler that the variable '''is subject to change externally (outside of the context of the loop), therefore it should reload the memory whenever it is referenced'''. |
Latest revision as of 02:21, 18 December 2016
This famous volatile variable article... Reading this article might just find you a job because C/C++ interviews tend to have this very common question on the list! The textbook definition of a volatile variable is: "Any variable that is subject to change externally should be declared volatile".
This often doesn't click in people's mind on what the volatile keyword actually does. It has to do with the way CPUs work and the way compilers optimize your programs. Let's assume that you are compiling in GCC with optimizations turned on and you're working on a loop until a certain bit is set :
// Assume you have a CPU register called UART_STATUS
// and you expect bit 0 to set sometime in near future
while(UART_STATUS & (1 << 0) == 0) {
; // Keep waiting
}
If UART_STATUS variable is not volatile, you've got a potential infinite loop even if the bit sets due to GCC optimization technique. Remember that CPUs have to bring information from MEMORY to REGISTERS and GCC may optimize your code such that MEMORY to REGISTER instruction is minimally used to enhance performance.
Assembly code without volatile:
LOAD R0, &UART_STATUS
LOOP:
CHECK R0, BIT0
JUMP LOOP IF R0
Assembly code *with* volatile:
LOOP:
LOAD R0, &UART_STATUS
CHECK R0, BIT0
JUMP LOOP IF R0
Compiler Optimization
The compiler basically optimizes the loop taking for granted that the memory variable UART_STATUS is not changing INSIDE the loop, therefore, there is no need for a (re)LOAD from memory instruction inside the loop. Using volatile keyword in this case tells the compiler that the variable is subject to change externally (outside of the context of the loop), therefore it should reload the memory whenever it is referenced.