2012-02-07 90 views
5

幾天前我接受了一次採訪,但仍然在尋找答案。 我想了解使用volatile關鍵字的意義。volatile&extern和有什麼不一樣?

找到下面的代碼:兩種不同的情況。

//project1 
//File1.c 

int abc;//Global variable 
/*And this variable is getting used in some other files too.*/ 
if(abc == 3) //Say 
{ 
    printf("abc == 3"); 
} 
else 
{ 
    printf("abc != 3"); 
} 
/*So if or else part will not be optimized 
because "abc" can not be predicted, 
the value can chage at any point of time */ 




//Project2 
//file1.c 

volatile int abc;//Global variable with volatile keyword 

/*And this variable is getting used in some other files too.*/ 

if(abc == 3) //Say 
{ 
    printf("abc == 3"); 
} 
else 
{ 
    printf("abc != 3"); 
} 
/*So if or else part will not be optimized 
because "abc" can not be predicted as it is declared as volatile, 
the value can chage at any point of time */ 

爲什麼我們應該使用volatile關鍵字呢?

+0

[靜態全局變量和靜態變量之間的區別是什麼?](http:// stackoverflow。com/questions/346306/what-is-a-static-global-and-static-volatile-variable) – NPE 2012-02-07 09:05:57

+5

volatile和extern完全不相關。 – 2012-02-07 09:07:15

+0

@MarkByers:你說得對,但根據面試官的問題,上述兩個都是一樣的。那麼爲什麼波動? – 2012-02-07 09:12:47

回答

5

正如Tony Delroy在其評論中解釋的那樣,externvolatile是完全不同的。


揮發性關鍵字保護您的變量從正在熱映的優化。優化的變量對其他線程是不可見的,永遠不會到達主內存。有時,如果不需要,編譯器可以爲even squeeze entirely一個變量。編譯器根據你的源代碼作爲唯一的輸入。有時候,有一些外部事件會改變你的變量值。例如,它可以是硬件設備或其他進程。

=>具體地說,編譯器會禁用一些優化到這個變量,所以它可以像你想要的那樣工作。


的extern是不是緩存內存VS。 Extern就是訪問存在於其他對象文件中的變量。請參閱this short example哪種彙編代碼是爲extern訪問生成的。 那些extern只要可能,變量在其自己的目標文件中被優化。保護與否不存在任何問題。

=>具體地,編譯器指示外部參考需要對在鏈接時

+0

幀指針和外部無關。幀指針用於棧變量(自動存儲類),extern是全局(靜態存儲類),不需要任何幀指針。 – Suma 2012-02-07 10:21:27

+0

該死的,我已經重新咀嚼,你說得對。我將刪除我的回答的這部分內容 – Coren 2012-02-07 10:29:04

+1

extern的解釋令人困惑。 – 2012-02-07 10:31:31

4

揮發性在聲明或原型說總是加載/存儲值從/到存儲器無論本地來解決,靜態extern這個vlaue(但在本地情況下它並不總是有意義的)。

還使用volatile關鍵字在常規來源是非典型的。它僅適用於將硬件寄存器映射到內存的硬件(如ARM架構中),以及內核/驅動程序開發的特殊情況。

如果您在GUI或電子商務代碼中使用易失性,那麼您可能是錯誤的...

+1

這個問題被標記爲嵌入式,其中volatile非常典型。自動(局部)變量中的易失性是有意義的,例如用於延遲實現的循環計數器:'for(volatile unsigned int i = delay; i> 0; --i){}'。由於循環沒有任何邏輯,優化器可以刪除它,如果它不是'volatile'。 – Gauthier 2012-02-09 10:53:34

+1

它也可用於創建例如一個調試變量,您可以在該變量中寫入程序從不讀取的變量,並打算稍後在調試器中讀取內容。 'static volatile uint8_t debug_buffer [64];'因爲編譯器發現保存的值不會被重用,所以它可以刪除寫操作。 'volatile'阻止了這一點。 – Gauthier 2012-02-09 10:59:08

+0

@ Gauthier謝謝你的建議!我記得有些嵌入式平臺允許在內存訪問某個地址時停止執行,因此您可以輕鬆跟蹤任何可變值更改,而不會通過將其標記爲volataile來降低執行性能。 – gavenkoa 2012-02-09 11:23:23

2

volatile通常是指一個或多個以下:

  1. 可變可以由另一個OS線程
  2. 執行的程序中的正常流可由信號被中斷,並且信號處理程序得到改變可能會改變執行的可變
  3. 正常流正在運行一個循環,該變量被循環內讀取,並且變量由點1或2
的裝置改變

volatile表示在程序的整個生命週期中,變量有兩個(或多個)讀取R1和R2,並且在R1和R2之間發生的其他事件會將變量更改爲正常執行流程之外的變量。


extern意味着變量已經某處別處定義和該程序重複使用的定義。

-1

本質上,volatile用於指示變量的值將被不同的線程修改。

聲明揮發性Java變量是指:

The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory"; 
Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself. 

的extern實質上意味着所有模塊可以使用定義的變量。

1

我不完全同意以前的答案,所以這裏是我的兩分錢。

通過聲明一個變量volatile,你告訴編譯器它的值可以在任何時候改變,並且它不能對變量的值做任何假設,即使在兩個連續的彙編指令中也是如此。結果任何變量的使用必須通過訪問實際變量而不是緩存值來完成。

在您提供的代碼中,abc之間沒有任何行爲差異,因爲if()/ else只評估一次變量。是有區別但是如果你改變了其他人通過第二個如果,如:

if(abc == 3) 
{ 
    printf("abc == 3"); 
} 
if (abc != 3) 
{ 
    printf("abc != 3"); 
} 

如果農行不聲明爲volatile,編譯器可以優化第二,如果和一個else語句來替換它,在後果ABC只會被讀取和評估一次,這意味着第一次或第二次打印將被執行(但不是兩者都是,也不是無)。

如果abc被聲明爲volatile(無論是局部的,全局的還是extern的),編譯器會被迫評估abc兩次,因爲它的值可能在兩者之間發生了變化。這意味着可以執行兩個打印中的任何一個或兩個或兩個打印。

Extern完全不同。它所做的只是告訴編譯器該變量已經在另一個文件中定義(其鏈接時將提供該地址)。如果編譯器可以預測abc的值在兩個if語句之間不會發生變化(編譯器可能如何並不重要),那麼它可能仍然會優化第二個if if into else並減少兩個abc評估爲1。

相關問題