這里的指標是可變的,而不是指向的值:
int* volatile ptr;
這里指向的值是可變的,而不是指標:
volatile int* p;
這里兩者都是易變的:
volatile int* volatile ptr;
在指標易失的第一種情況下,編譯器可以優化指向的值嗎?
知道我們也可以同時擁有指標和值 volatile 讓我認為編譯器可以優化只有指標是 volatile 時指向的值。這是真的?有什么好的應用程式或好的例子可能需要這樣做嗎?
uj5u.com熱心網友回復:
考慮這段代碼:
int * volatile ptr = SomeAddress;
printf("%d\n", *ptr);
printf("%d\n", *ptr);
編譯器無法優化第二個printf以使用與第一個相同的引數printf。它必須通過訪問 重新計算引數ptr,以防ptr發生更改。
考慮這段代碼:
int * volatile ptr = SomeAddress;
int x = *ptr;
printf("%d\n", x);
printf("%d\n", x);
編譯器可以優化第二個printf以使用與第一個相同的引數printf,因為它們都使用非易失性x。x的值先前是從 volatile 指標派生的這一事實無關緊要。
uj5u.com熱心網友回復:
在指標易失的第一種情況下,編譯器可以優化指向的值嗎?
通過“優化”,我認為您的意思是避免從主存盤器讀取。原則上,是的,這可以在指向非易失物件的易失指標的情況下完成。必須讀取指標值,但實作可以測驗新讀取的值以確定它是否需要從記憶體中讀取指向的物件。
然而,在實踐中,這種方法可能比無條件地從記憶體中讀取成本更高,因此我不希望 C 實作以這種方式“優化”。
知道我們也可以同時擁有指標和值 volatile 讓我認為編譯器可能會在只有指標是 volatile 時優化指向的值。這是真的?
有點。往上看。
有什么好的應用程式或好的例子可能需要這樣做嗎?
volatile并不是將優化本身作為一個目標。它是關于向編譯器指示物件的性質和用途,以便實作不會做出錯誤的假設。
如果指標的存盤在程式自己的 C 語言語意范圍之外發生變化,則應該宣告它volatile。如果指標的值可能指向受此類更改影響的物件,則指向的型別應該是volatile. 如果兩者兼而有之,則兩者兼而有之。在實踐中,需要一個指向 volatile 資料的指標并不常見,但需要一個 volatile 指標卻極為罕見。
uj5u.com熱心網友回復:
在指標易失的第一種情況下,編譯器可以優化指向的值嗎?
理論上它可以,例如,如果它可以推斷出指向的值與其他一些非限定指標指向的值相同。
int* b = ...;
int* volatile a = b;
// here `*b` can be optimized regardless of `a`.
在實踐中,你如何優化未知地址的東西?編譯器必須以某種方式知道上次訪問該特定地址時存盤的內容。通過易失性指標的每次訪問都涉及讀取該指標。
同樣,非限定指標不能給*volatile指標起別名,因為你永遠不能假設它們指向同一個地址。
volatilefor 指標在硬體暫存器又包含另一個暫存器的地址的情況下最有意義。但是那些罕見的情況會很volatile type* volatile有趣,或者更有可能volatile uint32_t*是取消參考以獲得一個整數,如果需要,它又會轉換為volatile uint32_t*指標。
我不記得曾經使用過type* volatile或volatile type* volatile在任何現實世界的系統中使用過,然后我主要撰寫低級驅動程式,如果在任何地方,你最有可能遇到這種情況。
uj5u.com熱心網友回復:
考慮這段代碼:
int test(int * volatile p)
{
int x = *p;
int y = *p;
return x;
}
編譯器需要生成讀取p 兩次的代碼,但它只需要取消參考p 一次即可計算x。y是一個死值,可以與計算它所需的取消參考一起消除。
現場演示(稍作修改以使跟蹤取消參考更容易)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/472092.html
