2012-09-24 47 views
8

我知道一個寄存器關鍵字將爲計算值分配一個寄存器,每當我們對變量執行一些計算並基本上不優化代碼時,volatile關鍵字將從內存中讀取值。所以,如果一個變量被分配了這兩個關鍵字,那麼這是否意味着它本質上會是自變量?我無法通過編寫示例代碼來理解行爲。任何人都可以點亮一下嗎?如何在C中註冊「volatile volatile int i」?

+3

什麼平臺和編譯器?我不認爲大多數通用編譯器(例如默認配置的GCC)都會尊重「註冊」。 – Joe

+2

'註冊'必須具備的一個效果是你不能接受一個變量聲明的地址。 –

+0

@Daniel:我不明白你的觀點。不能把變量的地址作爲?你的意思是說它可以被指針訪問嗎? – knightofhorizon

回答

13

在C中,register存儲類的行爲與auto存儲類的行爲完全相同,只是如果程序嘗試獲取或使用對象的地址(6.5)需要實現(每5.1.1.3)發佈診斷.3.2,6.7.1)。使用register作爲編譯器的優化提示通常是毫無意義的,因爲足夠聰明的編譯器可以利用非存儲的對象質量,這當然足夠聰明以跟蹤哪些對象可以被聲明register;相反,它應該被理解爲代碼質量檢查,程序員不會通過獲取對象的地址而無意中摧毀優化機會。

換句話說,從有效程序中刪除register關鍵字的所有實例對程序的語義沒有影響;它在這方面與static_assert類似。

volatile類型限定符指示訪問(讀取和寫入)對象被認爲是副作用,無法優化。對於一個對象,該對象不限定位置存儲器(即,具有register存儲類之一),這將是最有用的性能測試存在:

start = time(); 
for (multiple loops) 
    register volatile int result = test_function(); 
stop = time(); 
elapsed = stop - start; 
+0

我很好奇你的示例中的「register volatile」與簡單的'volatile'有什麼不同? – dasblinkenlight

+1

@dasblinkenlight沒有區別,因爲程序是有效的。 – ecatmur

+0

volatile關鍵字的一個更容易理解的視圖是,它告訴編譯器,無論何時指定了變量,編譯器都應該假定該變量可能已被某個其他進程或線程或設備改變。優化時的編譯器可以通過假設如果將變量值加載到寄存器中來消除重複訪問變量,則可以將寄存器中的值作爲該值的當前副本,直到編譯器找到修改該變量的源代碼。 Volatile告訴編譯器這個假設是無效的。 –

5

volatile意味着該對象可以這樣的方式改變對編譯器來說是不可預測的,並且register意味着它的地址不能被採用。

當這個對象實際上是平臺上的一個硬件寄存器時,兩者的結合就非常有意義。一些編譯器(例如gcc)甚至有擴展來修復這個變量到特定的硬件寄存器。

其他一些代碼可能會更改這樣的硬件寄存器,因此編譯器可能會對當前值不做任何處理。在這種情況下,添加const限定符甚至是有意義的。與海灣合作委員會的擴展E.g

register uint32_t volatile const eax __asm__("eax"); 

你必須檢查在任何時刻eax寄存器的工具,但你不能夠意外改變它。

+0

'volatile'也意味着所有對變量的寫入都必須實際發生。 –

+0

@TorKlingberg,你對「寄存器」變量的「寫入」意味着什麼。沒有這種變量的「存儲」模型,因此沒有「讀取」或「寫入」模型。 –