2012-11-02 28 views
6

民間,含義的揮發性對於陣列和類型轉換

考慮這個(可惡)一段代碼:

volatile unsigned long a[1]; 
unsigned long T; 

void main(void) 
{  
    a[0] = 0x6675636b; /* first access of a */ 
    T = *a; 
    *(((char *)a) + 3) = 0x64; /* second access of a */ 
    T = *a; 
} 

...這樣的問題:是((char *)a)易失性或非易失性?

這引出了一個更大的問題:應該在兩次訪問之間存在依賴關係嗎?也就是說,人類常識說有,但是C99標準說揮發性物質不會混淆非揮發性物質 - 所以如果((char *)a)是非揮發性的,那麼這兩個訪問就不會混淆,並且不存在依賴。

更正確地,C99 6.7.3(第5段)讀:

「如果試圖指與揮發性限定類型通過使用左值的具有非易失性定義的對象限定的類型,行爲是不確定的。「

所以當我們輸入字符串a時,volatile限定符是否適用?

+0

我想你回答了你自己的問題,它是未定義的。實際上,我認爲volatile不會產生任何影響,它是某種在通用平臺上被忽略的編譯器提示。 –

+1

@ AndrewTomazos-Fathomling「我認爲volatile不會產生任何影響,它是某種在常見平臺上被忽略的編譯器提示」您可能正在考慮「register」。在2012年的C代碼中,'volatile'類型限定符非常有意義,因爲當前(C語言)的時尚是積極的優化和嵌入式應用程序,兩者只能與程序員提示(如volatile)一起共存。 –

+1

@ AndrewTomazos-Fathomling,沒有'volatile'不僅是一個提示,它是一個命令來加載內存中的值在*每個*訪問。 –

回答

0

像你說的那樣,它的「未定義」。這意味着惡魔會從你的鼻子裏冒出來。請儘可能堅持「定義」行爲。 A volatile說明符將要求編譯器而不是優化該值,因爲它是一個「重要」和臨界值,如果由於不同的優化機制而發生更改,可能會導致問題。但是,這就是可以做的。

1

有疑問時,運行一些代碼:)我颳起了一些類似(略少可惡)測試代碼(win32的C++中MSVS 2K10應用程序)

int _tmain(int argc, _TCHAR* argv[]) { 
    int a = 0; 
    volatile int b = 0; 

    a = 1; //breakpoint 1 
    b = 2; //breakpoint 2 
    *(int *) &b = 0; //breakpoint 3 
    *(volatile int *) &b = 0; //breakpoint 4 

    return 0; 
} 

當編譯版本,允許我斷點在2和4,但不是1和3.

我的結論是,typecast決定行爲,1和3被優化了。直覺支持這一點 - 否則編譯器將不得不將所有內存位置的列表保持爲volatile,並檢查每個訪問(難看,難看),而不是僅將其與標識符的類型關聯(更簡單,更直觀) 。

我還懷疑它是編譯器特定的(甚至可能在編譯器中標記爲特定標誌),並會根據此行爲在任何平臺上進行測試。

其實從頭開始,我只想盡量不要依賴此行爲:)

另外,我知道你對數組具體要求,但我懷疑有差別。您可以輕鬆地爲陣列創建類似的測試代碼。