温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

volatile关键字

发布时间:2020-02-29 00:02:50 来源:网络 阅读:164 作者:flag不会倒 栏目:开发技术

首先简单介绍一下编译器对代码优化的概念:
编译器优化:在不影响程序结果的情况下,改变程序的执行顺序提高效率
优化级别有:
O0 O1 O2 O3
优先级别越高,优化的越厉害
如何优化?在此介绍volatile,我们只谈优化的一个方式,就是将频繁使用的变量直接加载到离cpu很近的寄存器中。

我们先来看如下代码:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int flag=1;
void Handler(int signo){
printf("signo=%d\n",signo);
flag=0;
}
int main(){
signal(2,Handler);
while(flag){}                                                                                                        
}

在不优化的情况下直接进行编译,我们可预见:程序运行起来,当给这个进程发送二号信号flag值才会变为0使循环结束程序运行结束。
但当用O2使编译器对这个代码进行优化时,就会发现按下ctrl+c发送2号信号时,循环依旧不会停止。这是为什么呢?
原来:
在编译器在优化过程中,若编译器判定某个数据是一个比较高的开销,然后编译器没有检测到有代码修改这个数据,便会把频繁使用的数据放到了寄存器中(while循环频繁使用flag,Handle函数虽对他进行修改但是由内核调用的,编译器并不知道),编译器就可能作出了错误的判断,这时就直接把flag这个值优化到寄存器里了,Handle函数对flag的修改只是改变了内存中的flag并没有改变寄存器中的flag,因而while判断时用到寄存器中的flag一直是1.所以循环就结束不了。
为了避免这种编译器的错误决措,我们引入volatile关键字
这个关键字修饰变量就是告诉编译器,这个变量必须每次都从内存中读,不敢直接加载到寄存器中,即volatile的目的就是保持内存可见性

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
volatile int flag=1;
void Handler(int signo){
printf("signo=%d\n",signo);
flag=0;
}
int main(){
signal(2,Handler);
while(flag){}                                                                                                        
}

在flag前加上volatile,这时候不管怎么优化flag都是从内存中读取的,一改变他就可以读入新的值,因而这个程序当接收到2信号时就可以正常退出了。

volatile要经常使用在多线程中,因为编译器对于多执行流的情况不太会判断,所以volatile经常要使用在多线程来让cpu用的变量都是新的。

与volatile相对的是register,即告诉编译器把这个变量放到寄存器中。
但是这register个关键字不经常用了因为编译器知道什么变量该放什么不该放,会自动优化。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI