[Zz] role of volatile

Source: Internet
Author: User
The role of volatile (
Http://blog.21ic.com/user1/2949/archives/2007/35599.html)

173 recommendation

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.
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:
Int square (volatile int * PTR)
{
Return * PTR ** PTR;
}
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 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 = * PTR;
Return a *;
} 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 will it appear (as stated on the first floor)

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

Supplement: Volatile should be interpreted as "direct access to the original memory address", which is quite 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, it is defined by volatile, it will not change either;

After being defined with volatile, this variable will not change because of external changes. You can use it with confidence. Let's see if the previous explanation (Variable-prone) is misleading.

------------ Concise example :------------------

The volatile keyword is a type modifier that uses the type variables it declares to indicate that it can be changed by unknown factors of 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.
An example of using this keyword is as follows:
Int volatile nvint;
>>>> When the value of a variable declared by volatile is required, the system always reads data from the memory where it is located, even if the previous command has just read data from it. The read data is saved immediately.
For example:
Volatile int I = 10;
Int A = I;
...
// Other code that does not explicitly tell the compiler to perform operations on I
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. Insert the assembly code to test whether the volatile keyword exists and the effect on the final code of the program is as follows:
>>>> First, use classwizard to create a Win32 console project, insert a voltest. cpp file, and enter the following code:
>
# I nclude <stdio. h>
Void main ()
{
Int I = 10;
Int A = I;
Printf ("I = % d", );
// The purpose of the following Assembly statement is to change the I value in the memory, but it does not let the compiler know
_ ASM {
MoV dword ptr [ebp-4], 20 h
}
Int B = I;
Printf ("I = % d", B );
}
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:
# I nclude <stdio. h>
Void main ()
{
Volatile int I = 10;
Int A = I;
Printf ("I = % d", );
_ ASM {
MoV dword ptr [ebp-4], 20 h
}
Int B = I;
Printf ("I = % d", B );
}
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!

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

The variable corresponding to volatile may change if your program does not know it.
For example, a multi-threaded program, multiple programs can manipulate this variable in the memory accessed together.
Your own program is unable to determine if this 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 it will not be executed at all.
If you write
For (volatile int I = 0; I <100000; I ++ );
It will execute

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

Static int I = 0;

Int main (void)
{
...
While (1)
{
If (I) dosomething ();
}
}

/* Interrupt service routine .*/
Void isr_2 (void)
{
I = 1;
}

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
The read operation from I to a register may be performed only once, and then only the "I copy" in this register is used for each if judgment, so that dosomething will never be
Call. 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 indicators have been read in half and are interrupted for rewriting). In 1, we can use the Guanzhong disconnection to implement
Task Scheduling can be disabled in 2, and in 3, it can only rely on the good design of hardware.

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.