?
Dieses Dokument verwendet PHP-Handbuch für chinesische Websites Freigeben
C類型系統(tǒng)中的每個單獨(dú)類型都具有該類型的多個限定版本,對應(yīng)于const,volatile中的一個,兩個或全部三個,并且對于指向?qū)ο箢愋偷闹羔槪拗葡薅ǚ?。該頁面描述?em style="font-style: italic;">volatile限定符的影響。
通過volatile限定類型的左值表達(dá)式進(jìn)行的每次訪問(包括讀取和寫入)都被認(rèn)為是可觀察的副作用,并且嚴(yán)格按照抽象機(jī)器的規(guī)則進(jìn)行評估(即,所有寫入均在在下一個序列點(diǎn)之前的某個時間)。這意味著在單個執(zhí)行線程中,相對于由易失性訪問序列點(diǎn)分隔的另一個可見副作用,無法優(yōu)化或重新排序易失性訪問。
將非易失性值轉(zhuǎn)換為易失性類型不起作用。要使用易失性語義訪問非易失性對象,必須將其地址強(qiáng)制轉(zhuǎn)換為易失性指針,然后必須通過該指針進(jìn)行訪問。
任何嘗試讀取或?qū)懭腩愋蜑関olatile的對象 - 通過非易失性左值限定會導(dǎo)致未定義的行為:
volatile int n = 1; // object of volatile-qualified typeint* p = (int*)&n;int val = *p; // undefined behavior
一個揮發(fā)性限定結(jié)構(gòu)或聯(lián)合類型的成員獲取它所屬類型的限定條件(在使用.
操作員或->
操作員進(jìn)行訪問時):
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類型限定符(通過使用typedef)聲明數(shù)組類型,則數(shù)組類型不是volatile限定的,但其元素類型為。如果一個函數(shù)類型被聲明為具有限定的volatile類型(通過使用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ù)組類型的方括號內(nèi)。它限定了數(shù)組類型被轉(zhuǎn)換的指針類型。以下兩個聲明聲明了相同的函數(shù):void f(double xvolatile,const double yvolatile); void f(double * volatile x,const double * volatile y); | (自C99以來) |
---|
指向非易失性類型的指針可以隱式轉(zhuǎn)換為指向相同或兼容類型的volatile限定版本的指針。逆轉(zhuǎn)換可以使用強(qiáng)制表達(dá)式來執(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
請注意,指向指針的指針T
不能轉(zhuǎn)換為指向指針的指針volatile T
; 對于兩種類型的兼容,其資格必須相同:
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
對象模型存儲器映射的I / O端口和static
const
volatile
對象模型存儲器映射的輸入端口,例如實時時鐘:
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
類型的對象sig_atomic_t
用于與signal
處理程序進(jìn)行通信。
3)volatile
包含setjmp
宏調(diào)用的函數(shù)的局部變量是保證在longjmp
返回后保留其值的唯一局部變量。
4)此外,可以使用volatile變量來禁用某些形式的優(yōu)化,例如,禁用dead store消除或?qū)icrobenchmarks進(jìn)行常量折疊。
請注意,volatile變量不適合線程之間的通信; 他們不提供原子性,同步或內(nèi)存排序。從另一個線程修改的易失性變量中讀取來自兩個未同步的線程的同步或并發(fā)修改是由于數(shù)據(jù)競爭造成的未定義行為。
演示了如何使用volatile來禁用優(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類型限定符(p:121-123)
C99標(biāo)準(zhǔn)(ISO / IEC 9899:1999):
6.7.3類型限定符(p:108-110)
C89 / C90標(biāo)準(zhǔn)(ISO / IEC 9899:1990):
3.5.3類型限定符