Role of volatile)

Source: Internet
Author: User
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) An Interrupted service subaccount Program Non-automatic variables that will be accessed in)
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.
If the subject correctly answers this question (well, I doubt this will happen), I will go a little deeper to 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 are the following function errors: 1 Int Square ( Volatile   Int   * PTR)
2 {
3 Return   * PTR *   * PTR;
4 }
5

 
The answer is as follows:
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 a service subroutine repairs a pointer to a buffer.
3). This sectionCodeThere is 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:

1 Int Square ( Volatile   Int   * PTR)
2 {
3 Int A, B;
4 A =   * PTR;
5 B =   * PTR;
6 Return A * B;
7 }
8

 
* 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:

1 Long Square ( Volatile   Int   * PTR)
2 {
3 Int A;
4 A =   * PTR;
5 Return A * A;
6 }
7

 

My understanding: (welcome to the dashboard ...~~!)
The key lies in two aspects:
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.

Here is an inaccurate example:
When paying, the accountant calls the employee to register their bank card number every time; once the accountant did not register immediately for convenience, he used the bank card number previously registered; an employee's bank card has been lost and the bank card number has been reported; as a result, the employee cannot receive the salary
Employee-original variable address
Bank Card number-backup of original variables in registers

2. under what circumstances (as stated on the first floor)
1 ). hardware registers of parallel devices (for example, Status Registers)
2 ). non-automatic variables accessed in an interrupt service subroutine
3 ). variables shared by several tasks in multi-threaded applications
supplement: Volatile should be interpreted as "direct access to the original memory address, the Explanation of "easy to change" is a bit misleading. "Easy to change" is caused by external factors, such as multithreading and interruptions. It is not because the variable modified by volatile is "easy to change, if there is no external cause, that is, the definition of volatile will not change. However, after the definition of volatile, this variable will not change because of external reasons, so you can use it with confidence; let's see if the previous explanation is misleading.

------------ simple example: ------------------
the volatile keyword is a type modifier. The type variable declared by it indicates that it can be changed by unknown factors of Some compilers. For example: operating system, 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.
example of using this keyword:
int volatile nvint;
>>> when the value of the variable declared by volatile is required, the system always reads data from the memory where it is located again, even if the command above reads data from it. The read data is saved immediately.
example:
volatile int I = 10;
int A = I;
...
// other code, which does not explicitly tell the compiler that I has been operated
int B = I;
volatile indicates that I may change at any time. Each time you use it, you must read it from the I address, therefore, the compilation code generated by the compiler will read data from the I address again and put it in B. The optimization method is that because the compiler finds that the code between the codes that read data from I has not performed any operations on I, it will automatically put the data that was last read in B. Instead of reading from I again. In this way, if I is a register variable or indicates that data on a port is prone to errors, volatile can ensure stable access to special addresses.
note: In vc6, code optimization is not performed in the general debugging mode, so the function of this keyword cannot be seen. Next, we will insert the assembly code to test whether the volatile keyword exists and the impact on the final code of the program:
>>> first, we will use classwizard to create a Win32 console project and insert a voltest. CPP file, enter the following code:
>>< br> Code

1 # Include < Stdio. h >  
2 Void Main ()
3 {
4 Int I = 10 ;
5 Int A = I;
6 Printf ( " I = % d " , );
7 // The purpose of the following Assembly statement is to change the I value in the memory, but it does not let the compiler know.
8 _ ASM
9 {
10 MoV dword ptr [EBP - 4 ], 20 h
11 }
12 Int B = I;
13 Printf ( " I = % d " , B );
14 }

 

Then, run the program in debug version mode and the output result is as follows:
I = 10
I = 32
Then, run the program in release version mode. The output result is as follows:
I = 10
I = 10
The output results obviously show that in the release mode, the compiler optimizes the code and does not output the correct I value for the second time. Next, we add the volatile keyword to the I statement to see what changes have taken place:Code

1 # Include < Stdio. h >  
2 Void Main ()
3 {
4 Volatile   Int I = 10 ;
5 Int A = I;
6 Printf ( " I = % d " , );
7 _ ASM {
8 MoV dword ptr [EBP - 4 ], 20 h
9 }
10 Int B = I;
11 Printf ( " I = % d " , B );
12 }
13

 

Run the program in the debug version and release version respectively, and the output is:
I = 10
I = 32
This indicates that this keyword plays its role!

------------------------------------

Variables corresponding to volatile may change when your program does not know it. For example, multiple programs can manipulate this variable in the multi-threaded program and memory accessed together, your own program cannot determine whether the variable is appropriate and will change. Also, for example, it corresponds to a certain state of an external device. When an external device is operating, the system changes the value of this variable through the driver and interrupt event, but your program does not know.
For volatile variables, the system extracts them directly from the corresponding memory every time it uses them, instead of using the original values in the cache, to adapt to its unknown changes, the system will not optimize the processing of such variables-obviously because its values may change at any time.

--------------------------------------------------------------------------------

Typical examples
For (INT I = 0; I <100000; I ++ );
This statement is used to test the speed of an empty loop, but the compiler must optimize it and will not execute it at all.
If you write
For (volatile int I = 0; I <100000; I ++ );
It will execute

Volatile is intended to be "changeable". Since the access speed of registers is faster than that of RAM, the compiler generally optimizes access to external Ram. For example:

1 Static   Int I = 0 ;
2 Int Main ( Void )
3 {
4 ...
5 While ( 1 )
6 {
7 If (I)
8 Dosomething ();
9 }
10 }
11
12 /* Interrupt service routine. */  
13 Void Isr_2 ( Void )
14 {
15 I = 1 ;
16 }
17

 

The program is intended to call the dosomething function in main when isr_2 is interrupted. However, since the compiler judges that I has not been modified in the main function, therefore, you may only perform one read operation from I to a register, and then use only the "I copy" in the register for each if judgment. As a result, dosomething will never be called. If the variable is modified with volatile, the compiler ensures that the read and write operations on the variable are not optimized (certainly executed ). In this example, I should also describe this.

Generally, volatile is used in the following areas::
1. Volatile must be added to the variable modified in the interrupted service program for testing by other programs;
2. Volatile should be added to the labels shared by all tasks in a multi-task environment;
3. Volatile is also required for the hardware registers mapped to memory, because each read/write to it may have different meanings;
In addition, in the above situations, we often need to consider data integrity at the same time (some of the correlated symbols have been read in half and are interrupted for rewriting). In 1, we can achieve this through Guanzhong disconnection, task Scheduling can be disabled in 2, and 3 can only rely on the good design of hardware. From: http://blog.21ic.com/user1/2949/archives/2007/35599.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.