程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++關鍵字volatile解析

C++關鍵字volatile解析

編輯:C++入門知識

  volatile在英文中的解釋是“不穩定的”,也就是說用該關鍵字修飾的變量的值隨時可能被改變。用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如:操作系統、硬件或者其它線程等。 volatile的本意是“易變的”,不過翻譯成“直接存取原始內存地址”更為合適。“易變”是因為外在因素引起的,象多線程,中斷等,並不是因為用volatile修飾了的變量就是“易變”了,假如沒有外因,即使用volatile定義,它也不會變化。
     計算機中進行計算時,通常會將數據拷貝到寄存器中,因為CPU對寄存器的操作遠快於對內存的操作。
    在變量沒有使用volatile修飾時,如果在計算過程中沒有對該變量所在的寄存器操作,計算機將認為該變量的值沒有變化,於是他就直接從寄存器中取值進行操作,而不會從內存/變量的源地址中取值。
    但是,如果變量使用了volatile關鍵字,則表明該變量的值隨時可能在編譯器認知的范圍之外被改變(例如在終端中被改變或者多任務、多線程)。而此時volatile關鍵字的作用就是告訴編譯器,不能擅自作出關於變量的值未改變的假設,每次進行計算時都從新從變量的源地址中取值,而不是取存放在寄存器中的拷貝。
    volatile關鍵字的語法和const的語法一樣。
    總之,關鍵字volatile作用是取消編譯器對被修飾的變量的任何優化,當對該變量進行操作時每次都是從他的源地址中讀寫,而不是從暫存數據的寄存器中讀取,即取消編譯器對此變量的優化。
    下面是幾個例子:
例子1、
void delay(int time)
{
for(;time>0;time--);
}
上面這段代碼本意是實現一個非精確的延時操作,通常來說沒有什麼問題,但是為了優化代碼,打開了編譯器的優化功能之後,這個函數將會被優化掉。因為,編譯器發現這個函數實際上什麼也沒有做,為了提高性能編譯器就會將這段代碼優化掉。
為了防止被編譯器優化掉,這段代碼可以改成下面:
volatile void delay(int time)//這裡用關鍵字volatile告訴編譯器不要講這段代碼優化
{
for(;time>0;time--);
}
例子2、
float square(volatile float *ptr)
{
return *ptr * *ptr;
}
這段代碼的問題在於形參使用了volatile關鍵字修飾,從而導致在調用這個函數的過程中*ptr的值可能被意外改變,其實它的過程如下  www.2cto.com
float square(volatile float *ptr)
{
float a, b;
a=*ptr;//在給a賦值之後,如果程序進入到中斷中改變了*ptr的值,則b的值和a不同
b=*ptr;
return a * b;
}
以上代碼應該改成:
float square(volatile float *ptr)
{
float a, b;
a=*ptr;
return a * a;
}
一般說來,volatile用在如下的幾個地方:

中斷服務程序中修改的供其它程序檢測的變量需要加volatile;
多任務環境下各任務間共享的標志應該加volatile;
存儲器映射的硬件寄存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義。
    另外,以上這幾種情況經常還要同時考慮數據的完整性(相互關聯的幾個標志讀了一半被打斷了重寫),在1中可以通過關中斷來實現,2中可以禁止任務調度,3中則只能依靠硬件的良好設計了。

作者:qingtingchen1987
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved