新网创想网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
首先简单介绍一下编译器对代码优化的概念:
编译器优化:在不影响程序结果的情况下,改变程序的执行顺序提高效率
优化级别有:
O0 O1 O2 O3
优先级别越高,优化的越厉害
如何优化?在此介绍volatile,我们只谈优化的一个方式,就是将频繁使用的变量直接加载到离cpu很近的寄存器中。
我们先来看如下代码:
#include
#include
#include
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
#include
#include
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个关键字不经常用了因为编译器知道什么变量该放什么不该放,会自动优化。
另外有需要云服务器可以了解下创新互联建站www.cdcxhl.com,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。