2012-02-07 16 views
5

Pochi giorni fa ho avuto un'intervista ma, ancora sto cercando la risposta. Mi piacerebbe capire l'importanza dell'uso di parole chiave volatili.Qual è la differenza tra volatile ed esterno?

Trova il codice qui sotto: Due diversi scenari.

//project1 
//File1.c 

int abc;//Global variable 
/*And this variable is getting used in some other files too.*/ 
if(abc == 3) //Say 
{ 
    printf("abc == 3"); 
} 
else 
{ 
    printf("abc != 3"); 
} 
/*So if or else part will not be optimized 
because "abc" can not be predicted, 
the value can chage at any point of time */ 




//Project2 
//file1.c 

volatile int abc;//Global variable with volatile keyword 

/*And this variable is getting used in some other files too.*/ 

if(abc == 3) //Say 
{ 
    printf("abc == 3"); 
} 
else 
{ 
    printf("abc != 3"); 
} 
/*So if or else part will not be optimized 
because "abc" can not be predicted as it is declared as volatile, 
the value can chage at any point of time */ 

Perché dovremmo usare parola chiave volatile, invece?

+0

possibile duplicato di [Qual è la differenza tra una variabile statica globale e variabile volatile?] (Http: // stackoverflow.it/questions/346306/what-is-the-difference-between-a-static-global-and-static-volatile-variable) – NPE

+5

volatile ed extern sono completamente indipendenti. –

+0

@MarkByers: hai ragione, ma secondo la domanda dell'intervistatore entrambi i precedenti servono lo stesso. Allora perché volatile? –

risposta

5

Come ha spiegato Tony Delroy nel suo commento, extern e volatile sono molto diversi.


Volatile parola chiave protegge la variabile da essere aggressivamente ottimizzato. Una variabile ottimizzata può essere invisibile ad altri thread e non raggiungere mai la memoria principale. A volte, il compilatore può even squeeze entirely una variabile se non è necessario. Il compilatore basa la sua ipotesi con il tuo codice sorgente come unico input. A volte, ci sono alcuni eventi esterni che possono modificare il valore della variabile. Ad esempio, potrebbe essere un dispositivo hardware o un altro processo.

=> Concretamente, il compilatore disabilita alcune ottimizzazioni per questa variabile, quindi può comportarsi come si desidera.


Esterno non è circa la cache vs memoria. Extern consiste solo nell'accedere a una variabile che risiede in altri file oggetto. Vedere this short example del tipo di codice assembly generato per l'accesso extern extern. Le variabili extern sono ottimizzate nel proprio file oggetto per quanto possibile. Non c'è dubbio sul fatto di proteggerlo o meno.

=> Concretamente, compilatore indica un riferimento esterno dover essere risolti in fase di collegamento

+0

I puntatori di frame e extern non sono correlati. I puntatori di frame vengono utilizzati per le variabili di stack (classe di archiviazione automatica), extern sono globali (classe di archiviazione statica) e non necessitano di alcun puntatore del frame. – Suma

+0

dannazione, ho re-cheched e hai ragione. Rimuoverò questa parte della mia risposta – Coren

+1

La spiegazione di extern è confusa. –

4

volatili in dichiarazione o prototipo dire sempre caricare/memorizzare valore da/a memoria indipendentemente locale, statica o extern questo vlaue (ma in caso di locale non è sempre significativo).

Anche l'utilizzo della parola chiave volatile in una fonte normale non è tipicamente. È utile solo per l'hardware che mappa i registri hardware in memoria (come nell'architettura ARM), in casi speciali di sviluppo di kernel/driver.

Se si utilizza volatile nella GUI o nel codice di e-commerce probabilmente si sbaglia ...

+1

La domanda è contrassegnata come incorporata, dove volatile è molto tipico. Volatile nelle variabili automatiche (locali) è significativo, ad esempio come contatori di loop per l'implementazione del ritardo: 'for (volatile unsigned int i = delay; i> 0; --i) {}'. Poiché il ciclo non ha nulla di logico, un ottimizzatore potrebbe rimuoverlo se non fosse per "volatile". – Gauthier

+1

È anche utile per creare ad es. una variabile di debug, in cui è possibile scrivere su una variabile che il programma non legge mai e che intende leggere il contenuto successivamente in un debugger. 'static volatile uint8_t debug_buffer [64];' Poiché il compilatore vede che i valori salvati non vengono mai riutilizzati, potrebbe anche essere sufficiente rimuovere la scrittura. 'volatile' lo impedisce. – Gauthier

+0

@ Gauthier Grazie in consiglio! Ricordo che alcune piattaforme incorporate consentono di interrompere l'esecuzione dell'accesso alla memoria a determinati indirizzi in modo da poter facilmente tracciare qualsiasi variazione di valore variabile senza perdere la performance di esecuzione contrassegnandola come volataile. – gavenkoa

2

volatile significa generalmente uno o più dei seguenti:

  1. La variabile potrebbe venir modificato da un altro filo OS
  2. Il normale flusso di esecuzione del programma può essere interrotto da un segnale e il gestore di segnale potrebbe modificare la variabile
  3. il normale flusso di esecuzione esegue un ciclo, la variabile viene letto all'interno del ciclo, e la variabile viene modificato mediante punto 1 o 2

volatile significa che per tutta la durata del programma ci sono due (o più) letture R1 e R2 della variabile, e qualche altro evento che accade tra R1 e R2 cambierà la variabile al di fuori del normale flusso di esecuzione.


extern significa che la variabile è stata definita da qualche parte altrove e che il programma è il riutilizzo di tale definizione.

-1

In sostanza, volatile viene utilizzato per indicare che il valore di una variabile verrà modificato da thread diversi.

Dichiarazione di variabile Java volatili significa:

The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory"; 
Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself. 

Esterno significa sostanzialmente che tutti i moduli possono utilizzare la variabile definita.

1

Non sono abbastanza d'accordo con le risposte precedenti, quindi ecco i miei due centesimi.

Dichiarando una variabile volatile stai dicendo al compilatore che il suo valore può cambiare in qualsiasi momento e che non può fare alcuna ipotesi sul valore della variabile, nemmeno in due istruzioni consecutive (assemblatore). Di conseguenza, qualsiasi utilizzo della variabile deve essere effettuato accedendo alla variabile effettiva e non a un valore memorizzato nella cache.

Nel codice fornito non vi è alcuna differenza comportamentale tra abc globale, extern o volatile perché if()/else valuta solo una volta la variabile. C'è una differenza se si modifica l'altro da una seconda, se, come in:

if(abc == 3) 
{ 
    printf("abc == 3"); 
} 
if (abc != 3) 
{ 
    printf("abc != 3"); 
} 

Se abc non è dichiarato volatile, il compilatore può ottimizzare il secondo se e sostituirlo con un'istruzione else, di conseguenza abc sarebbe solo letto e valutato una volta, ovvero il primo xo il secondo sarà eseguito (ma non entrambi e anche nessuno).

Se abc è dichiarato volatile (non importa se locale, globale o extern), il compilatore è costretto a valutare abc due volte perché il suo valore potrebbe essere cambiato in mezzo. Ciò significa che una qualsiasi delle due stampe, o entrambe, o nessuna, può essere eseguita.

Extern è una storia completamente diversa. Tutto ciò che fa è dire al compilatore che la variabile è stata definita in un altro file (il cui indirizzo sarà fornito al momento del collegamento). Se il compilatore può prevedere che il valore di abc non cambierà tra le due istruzioni if ​​(non importa come il compilatore potrebbe essere in grado di farlo), allora potrebbe ancora ottimizzare il secondo se in un altro e ridurre i due abc valutazioni a uno.

Problemi correlati