Viele Low-Level-Programme verwenden das flüchtige Schlüsselwort für Typen für die Speicherzuordnung und dergleichen, aber ich bin irgendwie verwirrt darüber, was es WIRKLICH im Hintergrund tut. Mit anderen Worten, was bedeutet es, wenn der Compiler die Speicheradresse nicht "wegoptimiert"?
9
volatile
Variablen herauslesen und es 5Antworten:
volatile
bedeutet, dass ein anderer Prozessor oder ein anderes E / A-Gerät oder etwas anderes die Variable unter Ihnen ändern kann.Bei einer normalen Variablen sind die Schritte Ihres Programms das einzige, was dies ändert. Wenn Sie beispielsweise
5
aus einer Variablen lesen und diese nicht ändern, enthält sie immer noch5
. Da Sie sich darauf verlassen können, muss sich Ihr Programm nicht die Zeit nehmen, die Variable das nächste Mal erneut zu lesen, wenn Sie sie verwenden möchten. Der C ++ - Compiler ist intelligent, um Code zu generieren, der sich nur an das erinnert5
.Aber Sie könnten es lesen als
5
, dann lädt das System möglicherweise Daten von der Festplatte in diesen Speicher und ändert sie in500
. Wenn Sie möchten, dass Ihr Programm den neuen Wert liest500
, muss der Compiler nicht zu schlau sein, wenn er den zuvor gelesenen Wert verwendet5
. Sie müssen es anweisen, den Wert jedes Mal neu zu laden. Dasvolatile
macht es.Eine Analogie für 5-Jährige
Nehmen wir an, Sie legen ein großes Blatt Papier auf einen Tisch. In einer Ecke des Papiers schreiben Sie die aktuelle Punktzahl eines laufenden Spiels auf
3 to 4
. Dann gehen Sie zur gegenüberliegenden Seite des Tisches und schreiben eine Geschichte über das Spiel. Ihr Freund, der das Spiel beobachtet, aktualisiert die Punktzahl in dieser Ecke im Verlauf des Spiels. Sie löscht3 to 4
und schreibt3 to 5
.Wenn Sie die Spielpunktzahl in Ihre Geschichte einfügen, können Sie entweder:
3 to 4
und nehmen Sie fröhlich an, dass sie sich nicht geändert hat (oder dass es Ihnen nichts ausmacht, wenn dies der Fall ist), oder3 to 5
jetzt ist) zu lesen , und gehen Sie zurück. So verhält sich einevolatile
Variable.quelle
volatile
bedeutet zwei Dinge:Der Wert der Variablen kann sich ändern, ohne dass Ihr Code ihn ändert. Wenn der Compiler den Wert der Variablen liest, kann er daher möglicherweise nicht davon ausgehen, dass er mit dem zuletzt gelesenen Wert identisch ist oder mit dem zuletzt gespeicherten Wert identisch ist, er muss jedoch erneut gelesen werden.
Das Speichern eines Werts in einer flüchtigen Variablen ist ein "Nebeneffekt", der von außen beobachtet werden kann, sodass der Compiler das Speichern eines Werts nicht entfernen darf. Wenn beispielsweise zwei Werte in einer Zeile gespeichert sind, muss der Compiler den Wert tatsächlich zweimal speichern.
Als Beispiel:
Der Compiler muss die Nummer zwei speichern, die Variable i lesen und die Variable speichern, die er in i eingelesen hat.
Es gibt eine andere Situation: Wenn eine Funktion verwendet
setjmp
und dannlongjmp
aufgerufen wird, wird garantiert, dass bei allen flüchtigen lokalen Variablen der Funktion der letzte Wert gespeichert wird - dies ist bei nichtflüchtigen lokalen Variablen nicht der Fall.quelle
i
und den Wert habenpi = &i
,x = *pi
wird geleseni
, aber es wird nicht garantiert, dass dieser Lesevorgang eine flüchtige Semantik aufweist.i
erklärt wird , wievolatile int i
dannpi
deklariert werden mußvolatile int *pi
, wobei in diesem Fall*pi
ist ein flüchtiger Zugang, nicht wahr?Abstrakte Erklärung
Sowohl C als auch C ++ haben das Konzept einer abstrakten Maschine . Wenn der Code den Wert einer Variablen verwendet, sagt die abstrakte Maschine, dass die Implementierung auf den Wert dieser Variablen zugreifen muss. Der Code des Formulars
statement_A; statement_B; statement_C;
muss genau in der angegebenen Reihenfolge ausgeführt werden. Ausdrücke, die diesen drei Anweisungen gemeinsam sind, müssen bei jedem Auftreten neu berechnet werden.Gemäß den abstrakten Maschinen
statement_A; statement_B; statement_C;
muss die Implementierung angesichts der Reihenfolge der Anweisungen zuerststatement_A
in ihrer Gesamtheit, dannstatement_B
und schließlich ausgeführt werdenstatement_C
. Die Implementierung kann sich nicht erinnern, dass Sieage
den Wert 5 zugewiesen haben. Jede Anweisung, auf die verwiesen wird,age
muss stattdessen auf den Wert dieser Variablen zugreifen.Das
volatile
Schlüsselwort wäre nicht erforderlich, wenn Implementierungen C- oder C ++ - Code gemäß den abstrakten Maschinenspezifikationen streng ausführen würden. Die abstrakten C- und C ++ - Maschinen haben kein Konzept von Registern, kein Konzept von allgemeinen Unterausdrücken, und die Ausführungsreihenfolge ist streng.Beide Sprachen haben auch Als-ob- Regeln. Eine Implementierung entspricht dem Standard, solange sich diese Implementierung so verhält, als hätte sie Dinge gemäß der abstrakten Maschinenspezifikation ausgeführt. Der Compiler kann davon ausgehen, dass nichtflüchtige Variablen keine Werte zwischen Zuweisungen ändern. Solange die
as-if
Regel nicht verletzt wird , kann die Sequenzstatement_A; statement_B; statement_C;
implementiert werden, indem ein Teil vonstatement_C
, dann ein Teil vonstatement_A
, dann alles vonstatement_B
, dann der Rest vonstatement_A
und schließlich der Rest von ausgeführt wirdstatement_C
.Diese Als-ob- Regeln gelten nicht für
volatile
Variablen. In Bezug aufvolatile
Variablen und Funktionen muss eine Implementierung genau das tun, was Sie ihr gesagt haben, und genau in der Reihenfolge, in der Sie ihr gesagt haben, dass sie Dinge tun soll.Die abstrakte Maschinenspezifikation hat einen Nachteil: Sie ist langsam. Ein positiver Aspekt von C und C ++ im Vergleich zu anderen Sprachen ist, dass sie ziemlich schnell sind. Dies wäre nicht der Fall, wenn Code für diese abstrakten Maschinen ausgeführt würde. Die Als-ob- Regeln ermöglichen es C und C ++, so schnell zu sein.
ELI5 Antwort
Das "Optimieren" einer Speicheradresse ist ein fortschrittliches Konzept, das nicht im Bereich der Fähigkeiten eines Fünfjährigen liegt. Konforme Fünfjährige tun genau das, was Sie ihnen sagen, nicht mehr und nicht weniger. Mit
volatile
sagen Sie der Implementierung, dass sie sich wie fünf verhalten soll: Kein Denken, keine ausgefallenen Optimierungen. Stattdessen muss die Implementierung genau das tun, was der Code vorschreibt.quelle
(nicht) flüchtig ist ein Hinweis für den Compiler, wie Code optimiert werden kann (aus Sicht des generierten Assembly-Codes):
quelle
Die Antworten scheinen ziemlich konsistent zu sein, aber es fehlt ein wichtiger Punkt. Sie teilen dem Compiler mit, dass Sie Speicherplatz zuweisen möchten, und für jeden Zugriff, lesen oder schreiben, möchten Sie, dass er diesen Zugriff ausführt. Wir möchten nicht, dass diese Zugriffe oder diese Variable aus irgendeinem Grund optimiert werden.
Ja, ein Grund ist, dass jemand anderes diesen Wert für uns ändern könnte. Ein weiterer Grund ist, dass wir diesen Wert möglicherweise für eine andere Person ändern. Dass jemand anderes es ist, der es für uns ändert oder für den wir es ändern, könnte Hardware / Logik oder Software sein. Es wird häufig verwendet, um Zugriffe auf Steuerungs- und Statusregister in eingebetteten Bare-Metal-Programmen zu definieren, die auf Hardware schreiben oder von dieser lesen. Sowie Software, die mit Software spricht, die in anderen Antworten erklärt wird.
Sie werden auch sehen, dass flüchtig verwendet wird, um zu steuern, wann und in welcher Reihenfolge die Zugriffe erfolgen, wenn Sie versuchen, einen Codeabschnitt zeitlich zu steuern, und Sie nicht flüchtig verwenden, müssen die fraglichen Variablen (Anfangszeit, Endzeit und Differenz) nur sein Gegen Ende berechnet, kann der Compiler eine der Zeitmessungen frei verschieben (nicht dort, wo wir sie platziert haben), nicht dass er nicht flüchtig ist, aber die Erfahrung zeigt, dass dies weniger wahrscheinlich ist.
Gelegentlich werden Sie sehen, dass es verwendet wurde, um einfach Zeit zu verbrennen. Ein elementarer LED-Blinker, die Hallo-Welt des Bare-Metal, verwendet möglicherweise einen flüchtigen Wert für eine Variable, die bis zu einer großen Anzahl zählt, nur um Zeit zu verbrennen, damit das menschliche Auge die LED sehen kann Zustand ändern. Fortgeschrittenere Beispiele verwenden dann Timer oder andere Ereignisse, um die Zeit zu verbrennen.
quelle