2012-03-29 9 views
57

volatile indica al compilatore di non ottimizzare il riferimento, in modo che ogni lettura/scrittura non utilizzi il valore memorizzato nel registro ma esegua un reale accesso alla memoria. Posso capire che è utile per alcune variabili ordinarie, ma non capisco come volatile influisca su un puntatore.Perché è utile un puntatore point-to-volatile, come "volatile int * p"?

volatile int *p = some_addr; 
int a = *p; // CPU always has to load the address, then does a memory access anyway, right? 

Qual è la differenza se è stato dichiarato come int *p = some_addr?

risposta

101

Un puntatore di modulo

volatile int* p; 

è un puntatore a un int che il compilatore tratterà come volatile. Ciò significa che il compilatore supporrà che sia possibile che la variabile a cui si riferisce p sia stata modificata anche se non vi è nulla nel codice sorgente che suggerisca che ciò potrebbe verificarsi. Ad esempio, se si imposta p in modo che punti a un numero intero regolare, ogni volta che si legge o scrive *p il compilatore è consapevole che il valore potrebbe essere stato modificato in modo imprevisto.

C'è un altro caso d'uso per un volatile int*: Se si dichiara una int come volatile, allora non si dovrebbe puntare ad essa con un regolare int*. Ad esempio, questa è una cattiva idea:

volatile int myVolatileInt; 
int* ptr = &myVolatileInt; // Bad idea! 

La ragione di questo è che il compilatore C non si ricorda che la variabile puntato dal ptr è volatile, quindi potrebbe cache il valore di *p in un registro non corretto . Infatti, in C++, il codice sopra riportato è un errore. Invece, si dovrebbe scrivere

volatile int myVolatileInt; 
volatile int* ptr = &myVolatileInt; // Much better! 

Ora, il compilatore ricorda che ptr punti a un volatile int, in modo da non (o non! Dovrebbe) cercare di ottimizzare gli accessi attraverso *ptr.

Un ultimo dettaglio: il puntatore che hai descritto è un puntatore a volatile int. È anche possibile fare questo:

int* volatile ptr; 

Questo dice che il puntatore è volatile, il che significa che il compilatore non dovrebbe cercare di memorizzare nella cache il puntatore nella memoria o cercare di ottimizzare il valore del puntatore perché il puntatore stesso potrebbe avere riassegnato da qualcos'altro (hardware, un altro thread, ecc) È possibile combinare questi insieme, se si desidera ottenere questa bestia:

volatile int* volatile ptr; 

questo dice che sia il puntatore e la pointee potrebbe ottenere cambiato inaspettatamente . Il compilatore non può ottimizzare il puntatore stesso e non può ottimizzare ciò che viene puntato.

Spero che questo aiuti!

+0

Penso che tu intenda "NON dovresti indicarlo con un normale int *" – markgz

+0

@ markgz- Whoops! Sì, è corretto. Fisso. – templatetypedef

+0

Penso che sia un errore anche in C, ma i compilatori C sono meno inclini a lamentarsi di mancate corrispondenze di tipo. –

6

Questo codice volatile int *p = some_addr dichiara un puntatore a volatile int. Il puntatore stesso non è volatile.

Nel caso improbabile che avevi bisogno il puntatore ad essere volatili così come l'int, si avrebbe bisogno di utilizzare:

volatile int * volatile p; 

non riesco a pensare a una situazione in cui si avrebbe bisogno di utilizzare tale .

+2

Esempio: I Sto usando 'uint8_t * volatile pData' volatile nel codice ISR che modifica il puntatore e i dati a cui punta. Il puntatore viene impostato dal codice principale e sia il puntatore che i dati vengono letti in seguito. – Christoph

Problemi correlati