A variable that is defined as volatile means that the variable may be unexpectedly changed so that the compiler does not assume the value of the variable. Precisely, the optimizer must carefully re-read the value of the variable each time it uses the variable, rather than using the backup stored in the register. Here are a few examples of volatile variables:
1). Hardware registers for parallel devices (e.g., status registers)
2). Non-automatic variables that are accessed in an interrupt service subroutine (non-automatic variables)
3). Variables shared by several tasks in multi-threaded applications
The person who cannot answer the question will not be hired. I think this is the most basic problem of distinguishing between C programmers and embedded system programmers. Embedded system programmers often deal with hardware, interrupts, RTOs, and so on, which require volatile variables. Not knowing volatile content will bring disaster.
Assuming that the interviewee answered the question correctly (well, wondering if this would be the case), I'll look at it a little bit and see if this guy knows exactly the importance of volatile.
1). Can a parameter be either const or volatile? explain why.
2). Can a pointer be volatile? explain why.
3). What is wrong with the following function:
int square (volatile int *ptr)
{
return *ptr * *PTR;
}
Here's the answer:
1). Yes. An example is a read-only status register. It is volatile because it can be changed unexpectedly. It is const because the program should not attempt to modify it.
2). Yes. Although this is not very common. An example is when a service subroutine fixes a pointer that points to a buffer.
3). There's a prank on this piece of code. The purpose of this code is to return the pointer *ptr to the square of the value, but since *ptr points to a volatile parameter, the compiler will produce code similar to the following:
int square (volatile int *ptr)
{
int A, B;
A = *ptr;
b = *ptr;
return a * b;
}
Because the values of the *ptr can be unexpectedly changed, A and B may be different. As a result, this code may return to the square value you expect! The correct code is as follows:
Long Square (volatile int *ptr)
{
int A;
A = *ptr;
Return a * A;
}
Tell me what I understand: (Welcome flogged ... ~~! )
The key is two places:
1. Compiler optimization (please help me to see the following understanding)
In this thread, when reading a variable, in order to improve the access speed, the compiler will sometimes read the variable into a register, and then, when the value of the variable is taken, the value is directly from the Register;
When the value of a variable changes in the line thread, the new value of the variable is copied to the register at the same time so that it remains consistent
When a variable changes value by another thread, the value of the register does not change accordingly, resulting in inconsistent values between the application read and the actual variable values
When the register changes values due to other threads, the value of the original variable does not change, causing the application to read values that are inconsistent with the actual variable values
To cite a less accurate example:
Payroll, accounting each time the employee called to register their bank card number; An accountant for the sake of convenience, no instant registration, the use of a previously registered bank card number; Just one employee's bank card was lost, the bank card number has been reported, thus causing the employee to receive no wages
Employee--Original variable address
Bank card number--backup of original variable in register
2. Under what circumstances will appear (as stated on the 1 floor)
1). Hardware registers for parallel devices (e.g., status registers)
2). Non-automatic variables that are accessed in an interrupt service subroutine (non-automatic variables)
3). Variables shared by several tasks in multi-threaded applications
Add: Volatile should be interpreted as "direct access to raw memory address" more appropriate, "variable" This explanation is a bit misleading;
"Volatile" is caused by external factors, such as multi-threading, interruption, not because the variable modified with volatile is "volatile", if there is no external cause, that is, using volatile definition, it will not change;
And with the definition of volatile, in fact, this variable will not be changed by external factors, you can rest assured that the use of the interpretation of the previous one (variable) is not misleading
------------Concise examples are as follows:------------------
The volatile keyword is a type modifier that declares a type variable that can be changed by factors unknown to the compiler, such as the operating system, hardware, or other threads. When you encounter a variable declared by this keyword, the compiler will no longer optimize the code that accesses the variable, providing stable access to the special address.
Examples of using this keyword are:
int volatile nvint;
>>>> when a variable declared with a volatile value is required, the system always reads the data back from the memory it is in, even if the preceding instruction has just read the data from there. And the read data is saved immediately.
For example:
volatile int i=10;
int a = i;
...
Other code does not explicitly tell the compiler that I have been manipulated
int b = i;
>>>>volatile points out that I is subject to change at any time and must be read from the address of I each time it is used, so the compiler generated assembly code will re-read the data from I's address in B. The optimization approach is that since the compiler found that the code between the I-read data two times does not operate on I, it automatically places the last-read data in B. Instead of re-reading from inside I. Thus, if I is a register variable or represents a port data is prone to error, so volatile can guarantee a stable access to the special address.
>>>> Note that in VC6, the General debug mode is not optimized for code, so the function of this keyword cannot be seen. This is done by inserting assembly code to test for the effect of a volatile keyword on the final code of the program:
>>>> first, build a Win32 console project with ClassWizard, 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", a);
The function of the following assembly statement is to change 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, running the program in debug version mode, the output is as follows:
i = 10
i = 32
Then, running the program in Release version mode, the output is as follows:
i = 10
i = 10
The results of the output clearly indicate that the compiler optimized the code in release mode and did not output the correct I value for the second time. Next, let's add the I statement to the volatile keyword to see what's changed:
#i nclude <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 debug and release versions, respectively, with the output:
i = 10
i = 32
This means that the keyword has played its part!
------------------------------------
Volatile variables may change in situations where your program does not know
such as multi-threaded programs, common access to the memory, a number of programs can manipulate this variable
Your own program, is unable to determine the appropriate variable will be changed
For example, he corresponds to a state of an external device, and when an external device is operating, through the driver and interrupt events, the system changes the value of the variable, and your program does not know it.
For volatile types of variables, the system will be used every time he is extracted from the corresponding memory, instead of using the original cache value, to adapt to its unknown when the changes will occur, the system does not optimize the processing of this variable-- It is also obvious that it is possible to change the value at any time.
--------------------------------------------------------------------------------
A typical example
for (int i=0; i<100000; i++);
This statement is used to test the speed of an empty loop.
But the compiler is definitely going to optimize it and not execute it at all.
If you write
for (volatile int i=0; i<100000; i++);
It's going to do it.
Volatile is meant to be "variable."
Because the access register is faster than RAM, the compiler generally makes optimizations to reduce access to external RAM. Like what:
static int i=0;
int main (void)
{
...
while (1)
{
if (i) dosomething ();
}
}
/* Interrupt Service routine. */
void isr_2 (void)
{
I=1;
}
The intent of the program is to call the DoSomething function in main when the isr_2 interrupt is generated, but because the compiler determines that I is not modified in the main function,
It is possible to perform only one read operation from I to a register, and then each time the if judge uses only the "I copy" inside the register, causing DoSomething to never be
Call. If you add a volatile modifier to a variable, the compiler guarantees that read and write operations on this variable will not be optimized (definitely executed). I should also explain this in this example.
Generally, volatile is used in several places:
1, the change in the Interrupt service program for other programs to detect variables need to add volatile;
2, multi-tasking environment to share the logo should be added volatile;
3, Memory mapping hardware register usually also add volatile description, because each time it read and write may be different meanings;
In addition, these situations often need to consider the integrity of the data at the same time (the correlation of several flags read half interrupted rewrite), in 1 can be closed by the interrupt to real
Now, 2 can prohibit task scheduling, 3 can only rely on the good hardware design.
Volatile use in Linux C