Cosa significa dichiarare una variabile volatile?

8

Molti programmi di basso livello usano la parola chiave volatile per i tipi di mappatura della memoria e simili, tuttavia sono un po 'confuso su ciò che REALMENTE fa in background. In altre parole, cosa significa quando il compilatore non "ottimizza" l'indirizzo di memoria?

    
posta Vikaton 12.01.2016 - 04:16
fonte

5 risposte

10

volatile significa che qualche altro processore o dispositivo I / O o qualcosa può cambiare la variabile da sotto di te.

Con una variabile ordinaria, i passaggi del tuo programma sono l'unica cosa che lo cambierà. Ad esempio, se leggi 5 da una variabile e non la modifichi, conterrà ancora 5 . Dal momento che puoi fare affidamento su questo, il tuo programma non deve prendersi del tempo per leggere di nuovo la variabile la prossima volta che vuoi usarla. Il compilatore C ++ è intelligente per generare codice che ricorda solo 5 .

Ma potresti leggerlo come 5 , quindi forse il sistema carica i dati dal disco in quella memoria, cambiandola in 500 . Se vuoi che il tuo programma legga il valore fresco 500 , devi fare in modo che il compilatore non sia troppo intelligente nell'usare il valore 5 precedentemente letto. Devi dirlo per ricaricare il valore ogni volta. Questo è ciò che volatile fa.

Un'analogia per i bambini di 5 anni
Diciamo che hai messo un grande foglio di carta su un tavolo. In un angolo del foglio, scrivi il punteggio attuale di un gioco in corso, 3 to 4 . Poi vai sul lato opposto del tavolo e inizia a scrivere una storia sul gioco. Il tuo amico che sta guardando il gioco aggiorna il punteggio in quell'angolo mentre il gioco procede. Cancella 3 to 4 e scrive 3 to 5 .

Quando vai a inserire il punteggio del gioco nella tua storia, puoi:

  1. scrivi l'ultimo punteggio che hai letto, 3 to 4 , assumendo allegramente che non sia cambiato (o non preoccuparti se lo ha fatto), o
  2. Fai un giro sul lato opposto del tavolo per leggere il punteggio corrente (che ora è 3 to 5 ) e torna indietro. Ecco come agisce una variabile volatile .
risposta data 12.01.2016 - 04:48
fonte
10

volatile significa due cose:

  1. Il valore della variabile può cambiare senza che il tuo codice lo modifichi. Pertanto, ogni volta che il compilatore legge il valore della variabile, può non assumere che è uguale all'ultima volta che è stato letto, o che è uguale all'ultimo valore memorizzato, ma deve essere letto di nuovo

  2. L'atto di memorizzare un valore in una variabile volatile è un "effetto collaterale" che può essere osservato dall'esterno, quindi il compilatore non può rimuovere l'atto di memorizzare un valore; ad esempio se due valori sono memorizzati in una riga, il compilatore deve effettivamente memorizzare il valore due volte.

Ad esempio:

i = 2; 
i = i; 

Il compilatore deve memorizzare il numero due, leggere la variabile i, memorizzare la variabile che ha letto in i.

C'è un'altra situazione: se una funzione usa setjmp e poi viene chiamata longjmp , tutte le variabili locali volatili della funzione sono garantite per avere l'ultimo valore memorizzato - questo non è il caso con variabili locali non volatili .

    
risposta data 12.01.2016 - 10:25
fonte
2

Spiegazione astratta
Sia C che C ++ hanno un concetto di macchina astratta . Quando il codice utilizza il valore di alcune variabili, la macchina astratta dice che l'implementazione deve accedere al valore di quella variabile. Il codice della forma statement_A; statement_B; statement_C; deve essere eseguito esattamente nell'ordine specificato. Le espressioni comuni a queste tre affermazioni devono essere ricalcolate ogni volta che si verificano.

Per le macchine astratte, data la sequenza di istruzioni statement_A; statement_B; statement_C; , l'implementazione deve prima eseguire statement_A nella sua interezza, quindi statement_B e infine statement_C . L'implementazione non può ricordare che hai assegnato age al valore di 5. Ogni istruzione che fa riferimento a age deve invece accedere al valore di tale variabile.

Non ci sarebbe bisogno della parola chiave volatile se le implementazioni eseguono rigorosamente codice C o C ++ secondo le specifiche della macchina astratta. Le macchine astratte C e C ++ non hanno alcun concetto di registri, nessun concetto di sottoespressioni comuni e l'ordine di esecuzione è rigoroso.

Entrambe le lingue hanno anche regole as-if . Un'implementazione è conforme allo standard fintanto che l'implementazione si comporta come se avesse eseguito le operazioni secondo le specifiche della macchina astratta. Il compilatore può assumere variabili non volatili che non cambiano i valori tra le assegnazioni. Finché non interrompe la regola as-if , la sequenza statement_A; statement_B; statement_C; potrebbe essere implementata eseguendo parte di statement_C , quindi parte di statement_A , quindi tutto statement_B , quindi il resto di statement_A e infine il resto di statement_C .

Quelle regole as-if non si applicano alle variabili volatile . Per quanto riguarda le variabili e le funzioni di volatile , un'implementazione deve fare esattamente ciò che gli hai detto di fare, esattamente nell'ordine in cui gli hai detto di fare le cose.

C'è uno svantaggio nelle specifiche astratte della macchina: è lento. Un aspetto positivo di C e C ++ rispetto ad altre lingue è che sono piuttosto veloci. Questo non sarebbe il caso se il codice fosse eseguito per queste macchine astratte. Le regole as-if sono ciò che permette a C e C ++ di essere così veloci.

risposta ELI5

what does it mean when the compiler doesn't "optimize away" the memory address?

"Ottimizzare" un indirizzo di memoria è un concetto avanzato, qualcosa che non rientra nel campo delle capacità di un bambino di cinque anni. I compiacenti di cinque anni faranno esattamente quello che tu dici loro di fare, né più né meno. Con volatile , stai dicendo all'implementazione di comportarsi come se fosse cinque: nessun pensiero, nessuna ottimistica fantasia. Invece, l'implementazione deve fare esattamente ciò che il codice gli dice di fare.

    
risposta data 12.01.2016 - 10:58
fonte
1

(non-) volatile è un suggerimento per il compilatore su come ottimizzare il codice (dal punto di vista del codice assembly generato):

  • non volatile significa che il tuo compilatore corrente decide dove verrà localizzata la variabile o in che modo il valore della variabile viene trasferito in una subroutine
    • in un indirizzo di memoria fissa,
    • nello stack [relativo allo stackpointer corrente dei processori],
    • sull'heap [relativo al basepointer corrente dei processori],
    • in un registro del processore,
    • ...
  • volatile significa che il compilatore non può ottimizzare la variabile perché qualcos'altro al di fuori del controller cpu-s principale (ad esempio un io-processer separato) può modificare questo valore.
risposta data 12.01.2016 - 10:57
fonte
0

Le risposte sembrano abbastanza coerenti ma mancano di un punto importante. Stai dicendo al compilatore che vuoi allocare spazio e per ogni accesso, leggi OPPURE SCRIVI, vuoi che esegua quell'accesso. Non vogliamo che ottimizzi questi accessi o quella variabile per qualche motivo.

Sì, una ragione è perché qualcun altro potrebbe cambiare quel valore per noi. Un'altra ragione è che potremmo cambiare quel valore per qualcun altro. Che qualcun altro sia quello che lo cambia per noi o quello per cui lo stiamo cambiando potrebbe essere hardware / logico o software. Viene spesso utilizzato per definire gli accessi ai registri di controllo e di stato nei programmi integrati in metallo nudo, scrivendo o leggendo dall'hardware. Così come il software che parla al software spiegato in altre risposte.

Vedrai anche volatile usato per controllare quando e in quale ordine si verificano gli accessi, se stai provando a temporizzare una sezione di codice, e non usi volatile le variabili in questione (ora di inizio, ora di fine e differenza) deve essere calcolato verso la fine del compilatore è libero di spostare una delle misurazioni del tempo (non dove le abbiamo posizionate), non che non può essere volatile ma l'esperienza lo dimostra meno probabile.

A volte, vedrai che è usato per bruciare semplicemente il tempo, un elementare led blinker, il ciao mondo di bare metal, potrebbe usare un volatile per una variabile che conta un numero elevato solo per bruciare il tempo per l'occhio umano vedere lo stato del cambiamento principale. Esempi più avanzati quindi utilizzando timer o altri eventi per bruciare il tempo.

    
risposta data 15.01.2016 - 03:43
fonte

Leggi altre domande sui tag