❤️ Xuemei was asked volatile during the interview ❤️, I explained an article clearly!

🎈 Author: Linux ape

🎈 Introduction: CSDN blog expert 🏆, C/C + +, interview, question brushing and algorithm. Please consult me, pay attention to me and chat privately if you have any questions!

🎈 Attention column: C/C + + interview customs collection (high quality articles are constantly updated...) 🚀

This article will explain the keyword volatile in C/C + +. It is rarely used in daily use, but it is often mentioned in the interview. Let's take a look at it in detail.

What is the role of volatile?

Volatile means changeable. It is a type modifier used in C/C + + to prevent the compiler from over Optimizing because it mistakenly recognizes that a piece of code cannot be changed by the code itself. Each time the compiler reads a variable defined by volatile, it takes a new value from the memory address.

There is a little doubt here. Isn't the compiler taking the value of a variable from memory?

Not all. The compiler sometimes takes the value of a variable from a register instead of from memory every time. Because the compiler thinks that the variables have not changed, it thinks that the value in the register is the latest. In addition, generally speaking, accessing the register is much faster than accessing the memory. The compiler may read the variables in the register for efficiency. However, the value of a variable in memory may be modified by other elements, such as hardware or other threads.

Let's take a practical example:

#include <stdio.h>

int main() {
    const int value = 10;
    int *ptr = (int*) &value;
  
    printf("Initial value : %d \n", value);

    *ptr = 100;
    printf("Modified value : %d \n", value);
    
    return 0;
}

Compile the program and execute the command:

linuxy@linuxy:~/volatile$ gcc main.c -o main

Output after operation:

linuxy@linuxy:~/volatile$ gcc main.c -o main
linuxy@linuxy:~/volatile$ ./main 
Initial value : 10 
Modified value : 100 
linuxy@linuxy:~/volatile$

You can see that the value of value has changed.

Next, take a look at the optimization of adding the - O parameter at compile time, and execute the command GCC - O main c -o main.

The output result is:

linuxy@linuxy:~/volatile$ gcc -O main.c -o main
linuxy@linuxy:~/volatile$ ./main 
Initial value : 10 
Modified value : 10 
linuxy@linuxy:~/volatile$

You can see that the value of value does not change after adding the - O parameter optimization. There is a problem here. Because the - O parameter is added, the compiler optimizes the code and ignores the change to the value of the variable.

-O parameters:

Using this parameter, the compiler attempts to reduce code size and execution time, but does not perform optimizations that require a lot of compilation time. Optimizing compilation takes more time, and it takes more memory for large functions.

Let's take a look at the comparison of the code size before and after optimization in the above example:

linuxy@linuxy:~/volatile$ gcc main.c -o main
linuxy@linuxy:~/volatile$ ls -al main
-rwxrwxr-x 1 linuxy linuxy 16752 7 June 18-14:38 main
linuxy@linuxy:~/volatile$ gcc -O main.c -o main
linuxy@linuxy:~/volatile$ ls -al main
-rwxrwxr-x 1 linuxy linuxy 16704 7 June 18-14:38 main
linuxy@linuxy:~/volatile$ 

As you can see, the optimized file becomes smaller.

Let's see what happens when the volatile keyword is added to the above code?

#include <stdio.h>

int main() {
    volatile const int value = 10;
    int *ptr = (int*) &value;
  
    printf("Initial value : %d \n", value);

    *ptr = 100;
    printf("Modified value : %d \n", value);

    return 0;
}

Execute command compiler:

linuxy@linuxy:~/volatile$ gcc -O main.c -o main

Output is:

linuxy@linuxy:~/volatile$ gcc -O main.c -o main
linuxy@linuxy:~/volatile$ ./main 
Initial value : 10 
Modified value : 100 
linuxy@linuxy:~/volatile$

It can be seen that even if the - O parameter optimizer is added, the value of value is still changed.  

Finally, take a look at how volatile is used.

1. Modify common variables

volatile Type variable

type volatile variable

volatile can be placed before and after the type. For example:

#include <stdio.h>

int main() {
    volatile int a = 10;
    int volatile b = 20;
    printf("a = %d\nb = %d\n", a, b);
}

Output after compilation:

linuxy@linuxy:~/volatile$ gcc -o main main.c
linuxy@linuxy:~/volatile$ ./main 
a = 10
b = 20
linuxy@linuxy:~/volatile$

2. Decorated pointer

The modifier pointer is similar to const (volatile and const are type modifiers) and has three forms:

volatile int *p;
int*  volatile p;
volatile type*  volatile variable;

Take a look at the specific code:

#include <stdio.h>

int main() {
    int a = 10;
    volatile int* p = &a;
    int* volatile q = &a;
    volatile int* volatile x = &a;

    printf("*p = %d\n*q = %d\n*x = %d\n", *p, *q, *x);
}

The compiled output is:

linuxy@linuxy:~/volatile$ gcc -o main main.c
linuxy@linuxy:~/volatile$ ./main 
*p = 10
*q = 10
*x = 10
linuxy@linuxy:~/volatile$ 

3. As a function parameter

As a function parameter, you should pay attention to, for example:

int square(volatile int *ptr)
{
        return *ptr * *ptr;
}

The compiler handles logic similar to the following:

int square(volatile int *ptr) 
{
    int a,b;
    a = *ptr;
    b = *ptr;
    return a * b;
}

Because ptr is declared volatile, the values of a and b may be different, so it is best to use the following method:

long square(volatile int *ptr) 
{
    int a;
    a = *ptr;
    return a * a;
}

reference:

[1] https://stackoverflow.com/questions/4437527/why-do-we-use-volatile-keyword

[2] https://www.geeksforgeeks.org/understanding-volatile-qualifier-in-c/

🎈 Welcome to praise 👍, Collection ⭐, Leaving a message. 💬

Added by MeanMrMustard on Sun, 16 Jan 2022 03:09:32 +0200