?
本文檔使用 PHP中文網(wǎng)手冊(cè) 發(fā)布
C類(lèi)型系統(tǒng)中的每個(gè)單獨(dú)類(lèi)型都具有該類(lèi)型的多個(gè)限定版本,對(duì)應(yīng)于const,volatile中的一個(gè),兩個(gè)或全部三個(gè),并且對(duì)于指向?qū)ο箢?lèi)型的指針,限制限定符。該頁(yè)面描述了volatile限定符的影響。
通過(guò)volatile限定類(lèi)型的左值表達(dá)式進(jìn)行的每次訪(fǎng)問(wèn)(包括讀取和寫(xiě)入)都被認(rèn)為是可觀察的副作用,并且嚴(yán)格按照抽象機(jī)器的規(guī)則進(jìn)行評(píng)估(即,所有寫(xiě)入均在在下一個(gè)序列點(diǎn)之前的某個(gè)時(shí)間)。這意味著在單個(gè)執(zhí)行線(xiàn)程中,相對(duì)于由易失性訪(fǎng)問(wèn)序列點(diǎn)分隔的另一個(gè)可見(jiàn)副作用,無(wú)法優(yōu)化或重新排序易失性訪(fǎng)問(wèn)。
將非易失性值轉(zhuǎn)換為易失性類(lèi)型不起作用。要使用易失性語(yǔ)義訪(fǎng)問(wèn)非易失性對(duì)象,必須將其地址強(qiáng)制轉(zhuǎn)換為易失性指針,然后必須通過(guò)該指針進(jìn)行訪(fǎng)問(wèn)。
任何嘗試讀取或?qū)懭腩?lèi)型為volatile的對(duì)象 - 通過(guò)非易失性左值限定會(huì)導(dǎo)致未定義的行為:
volatile int n = 1; // object of volatile-qualified typeint* p = (int*)&n;int val = *p; // undefined behavior
一個(gè)揮發(fā)性限定結(jié)構(gòu)或聯(lián)合類(lèi)型的成員獲取它所屬類(lèi)型的限定條件(在使用.
操作員或->
操作員進(jìn)行訪(fǎng)問(wèn)時(shí)):
struct s { int i; const int ci; } s;// the type of s.i is int, the type of s.ci is const intvolatile struct s vs;// the types of vs.i and vs.ci are volatile int and const volatile int
如果使用volatile類(lèi)型限定符(通過(guò)使用typedef)聲明數(shù)組類(lèi)型,則數(shù)組類(lèi)型不是volatile限定的,但其元素類(lèi)型為。如果一個(gè)函數(shù)類(lèi)型被聲明為具有限定的volatile類(lèi)型(通過(guò)使用typedef),則行為是未定義的。
typedef int A[2][3];volatile A a = {{4, 5, 6}, {7, 8, 9}}; // array of array of volatile intint* pi = a[0]; // Error: a[0] has type volatile int*
在函數(shù)聲明中,關(guān)鍵字volatile可能出現(xiàn)在用于聲明函數(shù)參數(shù)數(shù)組類(lèi)型的方括號(hào)內(nèi)。它限定了數(shù)組類(lèi)型被轉(zhuǎn)換的指針類(lèi)型。以下兩個(gè)聲明聲明了相同的函數(shù):void f(double xvolatile,const double yvolatile); void f(double * volatile x,const double * volatile y); | (自C99以來(lái)) |
---|
指向非易失性類(lèi)型的指針可以隱式轉(zhuǎn)換為指向相同或兼容類(lèi)型的volatile限定版本的指針。逆轉(zhuǎn)換可以使用強(qiáng)制表達(dá)式來(lái)執(zhí)行。
int* p = 0;volatile int* vp = p; // OK: adds qualifiers (int to volatile int)p = vp; // Error: discards qualifiers (volatile int to int)p = (int*)vp; // OK: cast
請(qǐng)注意,指向指針的指針T
不能轉(zhuǎn)換為指向指針的指針volatile T
; 對(duì)于兩種類(lèi)型的兼容,其資格必須相同:
char *p = 0;volatile char **vpp = &p; // Error: char* and volatile char* are not compatible typeschar * volatile *pvp = &p; // OK, adds qualifiers (char* to char*volatile)
1)靜態(tài)volatile
對(duì)象模型存儲(chǔ)器映射的I / O端口和static
const
volatile
對(duì)象模型存儲(chǔ)器映射的輸入端口,例如實(shí)時(shí)時(shí)鐘:
volatile short *ttyport = (volatile short*)TTYPORT_ADDR;for(int i = 0; i < N; ++i) *ttyport = a[i]; // *ttyport is an lvalue of type volatile short
2)static
volatile
類(lèi)型的對(duì)象sig_atomic_t
用于與signal
處理程序進(jìn)行通信。
3)volatile
包含setjmp
宏調(diào)用的函數(shù)的局部變量是保證在longjmp
返回后保留其值的唯一局部變量。
4)此外,可以使用volatile變量來(lái)禁用某些形式的優(yōu)化,例如,禁用dead store消除或?qū)icrobenchmarks進(jìn)行常量折疊。
請(qǐng)注意,volatile變量不適合線(xiàn)程之間的通信; 他們不提供原子性,同步或內(nèi)存排序。從另一個(gè)線(xiàn)程修改的易失性變量中讀取來(lái)自?xún)蓚€(gè)未同步的線(xiàn)程的同步或并發(fā)修改是由于數(shù)據(jù)競(jìng)爭(zhēng)造成的未定義行為。
演示了如何使用volatile來(lái)禁用優(yōu)化。
#include <stdio.h>#include <time.h> int main(void){ clock_t t = clock(); double d; for (int n=0; n<10000; ++n) for (int m=0; m<10000; ++m) d += d*n*m; // reads and writes to a non-volatile printf("Modified a non-volatile variable 100m times. " "Time used: %.2f seconds\n", (double)(clock() - t)/CLOCKS_PER_SEC); t = clock(); volatile double vd; for (int n=0; n<10000; ++n) for (int m=0; m<10000; ++m) vd += vd*n*m; // reads and writes to a volatile printf("Modified a volatile variable 100m times. " "Time used: %.2f seconds\n", (double)(clock() - t)/CLOCKS_PER_SEC);}
可能的輸出:
Modified a non-volatile variable 100m times. Time used: 0.00 seconds Modified a volatile variable 100m times. Time used: 0.79 seconds
C11標(biāo)準(zhǔn)(ISO / IEC 9899:2011):
6.7.3類(lèi)型限定符(p:121-123)
C99標(biāo)準(zhǔn)(ISO / IEC 9899:1999):
6.7.3類(lèi)型限定符(p:108-110)
C89 / C90標(biāo)準(zhǔn)(ISO / IEC 9899:1990):
3.5.3類(lèi)型限定符