2010-03-19 2 views
22

Si consideri il seguente codice:Perché il parassita 'volatile' è in C++?

int main()                  
{                    
    int i;                  
    volatile int* p = &i;              
    int *v = p;                 
    return 0;                 
} 

Questo dà un errore in g++:

$ g++ -o volatile volatile.cpp 
volatile.cpp: In function ‘int main()’: 
volatile.cpp:6: error: invalid conversion from ‘volatile int*’ to ‘int*’ 

La mia intenzione era che voglio fare p volatile. Tuttavia, una volta letto il valore di p, non mi interessa se l'accesso a v è volatile. Perché è richiesto che v sia dichiarato volatile?

Questo è ovviamente un codice ipotetico. In una situazione reale, è possibile immaginare che p punti in una posizione di memoria, ma viene modificato esternamente e voglio v in modo che punti al momento di v = p, anche se successivamente p viene modificato esternamente. Pertanto, p è volatile, ma non lo è v.

A proposito, sono interessato al comportamento sia quando questo è considerato C e C++, ma in C questo genera solo un avviso, non un errore.

+2

Gli standard non conoscono la differenza tra un avviso e un errore. È la scelta del compilatore come gestire una violazione, fintanto che riporta almeno un messaggio per il programma. –

+2

forse vuoi una copia di p in v? – slf

risposta

36

Se vuoi dire che il puntatore dovrebbe essere volatile, piuttosto che l'oggetto a cui punta, allora dichiareremo come

int* volatile p; 
+7

Questa è la tua risposta, Steve. Vorrei aggiungere questo consiglio: * Scrivi sempre il qualificatore const/volatile ** dopo ** quello che volevi qualificare. * È l'unico modo per scrivere qualificatori * coerentemente *, perché puoi scrivere sia 'volatile int' e 'int volatile' quando vuoi un intero volatile, ma solo 'int * volatile' ti darà un puntatore * volatile *. – DevSolar

+0

Grazie !!! Non ci ho nemmeno pensato. Completamente logico, grazie. – Steve

+1

Il modo più semplice per leggere le dichiarazioni (sia per il posizionamento const sia per quello volatile) è semplicemente leggerle all'indietro. Quindi "int * volatile" è un "puntatore volatile a un int". – Adisak

14

In C++ la parola volatile applica gli stessi tipi di restrizioni su cosa si può fare come const fa. Lo standard si riferisce a questo come "qualifica cv" come in "qualifica const/volatile". I conts possono essere usati solo dai conts, e allo stesso modo i volatili possono essere usati solo dai volatili.

Solo a parte questo può aiutarti a scrivere codice multithread. Non in virtù dell'impiego di qualche magia del compilatore che rende improvvisamente atomica la sua variabile o qualcosa del genere, ma costringendoti ad agire solo su dati volatili in modo volatile. Vedi questo Alexandrescu article per maggiori informazioni.

+0

Vale anche la pena leggere: http://www.mikeash.com/pyblog/friday-qa-2009-07-10-type-specifiers-in-c-part-3.html (alias non dimenticare di OSMemoryBarrier) – slf