Volatile Concept
Volatile is variable and unstable.
Like const, the volatile keyword is a type modifier. Variables modified by volatile indicate that they can be changed by unknown factors in some compilers, such as operating systems, hardware, or other threads. When the variable declared by this keyword is encountered, the compiler will not optimize the code that accesses the variable, so as to provide stable access to the special address.
Let's take a look at the following example: int I = 10; int j = I; // (1) Statement int k = I; // (2) the compiler optimizes the code at this time, because in statements (1) and (2), I is not used as the left value. At this time, the compiler considers that the value of I has not changed. Therefore, after the I value is obtained from the memory in the (1) Statement and assigned to j, this value is not lost, instead, this value is used to assign a value to k in the (2) statement. The compiler does not generate assembly code to retrieve the I value from the memory again, which improves the efficiency. Note: (1), (2) the I between statements is not used as the left value. Let's look at another example: volatile int I = 10; int j = I; // (3) Statement int k = I; // (4) the volatile keyword of the statement tells the compiler that I may change at any time. Each time you use it, you must retrieve the I value from the memory, therefore, the compilation code generated by the compiler will re-read data from the address of I and put it in k.
In this case, if I is a register variable, a port data, or shared data of multiple threads, it is prone to errors. Therefore, volatile can ensure stable access to special addresses.
A variable defined as volatile means that this variable may be unexpectedly changed, so that the compiler will not assume the value of this variable. Precisely, the optimizer must carefully re-read the value of this variable every time when using this variable, rather than using the backup stored in the register. The following are examples of volatile variables:
1). Hardware registers of parallel devices (for example, Status Registers)
2). Non-automatic variables that will be accessed in an interrupt service subroutine)
3) variables shared by several tasks in multi-threaded applications
People who cannot answer this question will not be hired. I think this is the most basic problem to distinguish between C programmers and embedded system programmers. Embedded System programmers often deal with hardware, interruptions, RTOS, and so on, all of which require volatile variables. If you do not know volatile content, it will lead to disasters.
Volatile Problems
If the subject correctly answers these questions (well, I doubt if this is the case), I will take a closer look and see if this guy understands the full importance of volatile. 1) can a parameter be const or volatile? Explain why. 2) can a pointer be volatile? Explain why. 3) What is the error in the following function: int square (volatile int * ptr) {return * ptr ** ptr;} The answer below is: 1). Yes. One example is read-only status registers. It is volatile because it may be unexpectedly changed. It is const because the program should not try to modify it. 2). Yes. Although this is not very common. One example is when an interrupt service subroutine repairs a pointer to a buffer. 3) This code has a prank. The purpose of this Code is to return the pointer * ptr points to the square of the value. However, since * ptr points to a volatile parameter, the compiler will generate code similar to the following: int square (volatile int * ptr) {int a, B; a = * ptr; B = * ptr; return a * B ;} * The value of * ptr may be unexpectedly changed, so a and B may be different. As a result, this Code may not return the expected square value! The correct code is as follows: long square (volatile int * ptr) {int a; a = * ptr; return a * ;}
Summary
1. Compiler Optimization (please help me understand the following)
In this thread, when reading a variable, in order to improve the access speed, the compiler sometimes first reads the variable to a register during optimization; later, when getting the variable value, directly from the register;
When the variable value changes in this thread, the new value of the variable will be copied to this register at the same time to maintain consistency.
When the value of a variable changes due to other threads, the value of this register will not change accordingly, resulting in inconsistent values read by the application and the actual value of the variable.
When the value of this register is changed due to other threads, the value of the original variable will not change, resulting in inconsistent values read by the application and the actual variable value.
2. Under what circumstances will this happen?
Hardware registers of parallel devices (for example, Status Registers)
Non-automatic variables accessed in an interrupt service subroutine)
Variables shared by several tasks in multi-threaded applications
Supplement: volatile should be interpreted as "direct access to the original memory address", which is quite misleading;