C语言中volatile关键字的作用

volatile 的作用 是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。

int i = 10;
int main(void){
    int a, b;
    a = i;
    ...//伪代码,里面不含有对 a 、 b 以及 i的操作
    b = i;
    if(a == b){
        printf("a = b");
    }
    else {
        printf("a != b");
    }
    return 0;
}

如上代码,如果选择编译器优化,可能会被编译成如下代码(当然不是在C语言层面上优化,而是在汇编过程优化,只是使用C程序举例):

int i = 10;
int main(void){
    int a, b;
    a = i;
    ...//伪代码,里面不含有对 a 、 b 以及 i的操作
    b = i;
    printf("a = b");
    return 0;
}

因为在仅仅从main主函数来看,a == b是必然的,那么在什么情况,a 和 b不是必然相等呢?

1. i 是其他子线程与主线程共享的全局变量,其他子线程有可能修改 i 值;

2. i 是中断函数与主函数共享的全局变量,中断函数有可能修改 i 值;

3. i 属于硬件寄存器,CPU可能通过硬件直接改变 i 的值(例如寄存器的标志位)

volatile 常见的几个面试题

1、一个参数既可以是const还可以是volatile吗?

可以,例如只读的状态寄存器。它是 volatile 因为它可能被意想不到地改变。它是 const 因为 程序不应该试图去修改它。

2、一个指针可以是 volatile 吗?

可以,当一个中服务子程序修改一个指向一个 buffer 的指针时。

3、下面的函数有什么错误:

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

这段代码的目的是用来返指针* ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

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

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

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

总结:

volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如 果没有 volatile 关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。所以遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问


谢谢大佬们的文章,转自: https://blog.csdn.net/weixin_38815998/article/details/102840096?spm=1001.2101.3001.6650.4&depth_1-utm_relevant_index=8

https://juyou.blog.csdn.net/article/details/54024070?spm=1001.2101.3001.6650.1&depth_1-utm_relevant_index=2

你可能感兴趣的:(C语言,c语言,开发语言)