Detailed Explanation of the volatile Keyword in C/C++
Category Programming Techniques
1. Why Use volatile?
The volatile keyword in C/C++ corresponds to const and is used to modify variables, typically to establish a memory barrier at the language level. This is BS's explanation of the volatile modifier in "The C++ Programming Language":
>
A volatile specifier is a hint to a compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided.
The volatile keyword is a type modifier, and variables declared with it indicate that they can be changed by factors unknown to the compiler, such as operating systems, hardware, or other threads. When the compiler encounters a variable declared with this keyword, it refrains from optimizing the code that accesses the variable, thus providing stable access to special addresses. The syntax for declaration is: int volatile vInt;
When the value of a variable declared with volatile is required, the system always reads the data from its memory location, even if the instruction just before it has just read the data from there. And the read data is immediately saved. For example:
volatile int i=10;
int a = i;
...
// Other code, without explicitly telling the compiler that an operation has been performed on i
int b = i;
Volatile indicates that i may change at any time, and each time it is used, it must be read from the address of i, so the assembly code generated by the compiler will read the data from the address of i and place it in b. The optimized approach is that since the compiler finds that there is no operation on i between the two codes that read data from i, it will automatically place the last read data in b. Instead of reading it again from i. This way, if i is a register variable or represents a port data, it is easy to make a mistake, so it can be said that volatile can ensure stable access to special addresses. Note that in VC 6, the general debug mode does not perform code optimization, so the role of this keyword is not obvious. The following is an example of inserting assembly code to test the impact of the presence or absence of the volatile keyword on the final code of the program, enter the following code:
Example
#include <stdio.h>
void main()
{
int i = 10;
int a = i;
printf("i = %d", a);
// The following assembly statement changes the value of i in memory
// But it does not let the compiler know
__asm {
mov dword ptr [ebp-4], 20h
}
int b = i;
printf("i = %d", b);
}
Then, run the program in Debug mode, and the output is as follows:
i = 10
i = 32
Then, run the program in Release mode, and the output is as follows:
i = 10
i = 10
The output results clearly show that in Release mode, the compiler has optimized the code, and the second time it did not output the correct value of i. Next, let's add the volatile keyword to the declaration of i and see what changes:
Example
#include <stdio.h>
void main()
{
volatile int i = 10;
int a = i;
printf("i = %d", a);
__asm {
mov dword ptr [ebp-4], 20h
}
int b = i;
printf("i = %d", b);
}
Run the program in both Debug and Release modes, and the output is:
i = 10
i = 32
This shows that the volatile keyword has played its role. In fact, it is not only embedded assembly manipulating the stack that belongs to the compiler cannot recognize the variable change, but more likely it is the concurrent access to shared variables by multiple threads, and one thread changes the value of the variable, how to make the changed value visible to other threads. Generally, volatile is used in the following places:
1) Variables modified in the interrupt service program for other programs to detect need to be added volatile;
2) Flags shared between tasks in a multitasking environment should be added volatile;
3) Memory-mapped hardware registers usually also need to be marked with volatile, because each read and write to it may have a different meaning;
2. Volatile Pointers
Similar to the const modifier, const has the concepts of constant pointers and pointer constants, and volatile also has corresponding concepts:
Modifying the object pointed to by the pointer, the data is const or volatile: