Unterschied zwischen const und const volatile

Lesezeit: 8 Minuten

Benutzeravatar von user559208
Benutzer559208

Wenn wir eine Variable als deklarieren volatile jedes Mal, wenn der frische Wert aktualisiert wird
Wenn wir eine Variable als deklarieren const dann wird der Wert dieser Variablen nicht geändert

Dann const volatile int temp;

Was nützt es, die Variable zu deklarieren temp wie oben?
Was passiert, wenn wir als erklären const int temp?

  • Sie würden nicht verwenden const volatile int temp; im Blockbereich (dh innerhalb { }), hat es dort keine Verwendung.

    – MM

    15. Februar 2016 um 21:57 Uhr


Benutzeravatar von Michael Burr
Michael Burr

Ein Objekt, das als markiert ist const volatile darf nicht durch den Code verändert werden (es wird ein Fehler ausgelöst wegen der const Qualifizierer) – zumindest durch diesen bestimmten Namen/Zeiger.

Das volatile Teil des Qualifizierers bedeutet, dass der Compiler den Zugriff auf das Objekt nicht optimieren oder neu anordnen kann.

In einem eingebetteten System wird dies normalerweise verwendet, um auf Hardwareregister zuzugreifen, die von der Hardware gelesen und aktualisiert werden können, aber keinen Sinn zum Schreiben machen (oder möglicherweise ein Fehler beim Schreiben sind).

Ein Beispiel könnte das Statusregister für eine serielle Schnittstelle sein. Verschiedene Bits zeigen an, ob ein Zeichen darauf wartet, gelesen zu werden, oder ob das Senderegister bereit ist, ein neues Zeichen anzunehmen (dh – es ist leer). Jeder Lesevorgang dieses Statusregisters könnte zu einem anderen Wert führen, je nachdem, was sonst noch in der Hardware der seriellen Schnittstelle vorgefallen ist.

Es macht keinen Sinn, in das Statusregister zu schreiben (abhängig von der jeweiligen Hardwarespezifikation), aber Sie müssen sicherstellen, dass jeder Lesevorgang des Registers zu einem tatsächlichen Lesevorgang der Hardware führt – die Verwendung eines zwischengespeicherten Werts aus einem vorherigen Lesevorgang wird ‘ t informieren Sie über Änderungen im Hardwarezustand.

Ein kurzes Beispiel:

unsigned int const volatile *status_reg; // assume these are assigned to point to the 
unsigned char const volatile *recv_reg;  //   correct hardware addresses


#define UART_CHAR_READY 0x00000001

int get_next_char()
{
    while ((*status_reg & UART_CHAR_READY) == 0) {
        // do nothing but spin
    }

    return *recv_reg;
}

Wenn diese Zeiger nicht als Being volatilekönnen einige Probleme auftreten:

  • Der While-Schleifentest könnte das Statusregister nur einmal lesen, da der Compiler davon ausgehen könnte, dass sich das, worauf er zeigte, niemals ändern würde (es gibt nichts im While-Schleifentest oder in der Schleife selbst, was dies ändern könnte). Wenn Sie die Funktion eingegeben haben, als kein Zeichen in der UART-Hardware wartete, könnten Sie in einer Endlosschleife landen, die nie angehalten wird, selbst wenn ein Zeichen empfangen wurde.
  • Das Lesen des Empfangsregisters könnte vom Compiler vor die While-Schleife verschoben werden – wiederum, weil nichts in der Funktion darauf hinweist *recv_reg durch die Schleife geändert wird, gibt es keinen Grund, warum es nicht gelesen werden kann, bevor es in die Schleife eintritt.

Das volatile Qualifizierer stellen sicher, dass diese Optimierungen nicht vom Compiler durchgeführt werden.

  • +1 zur Erklärung. Und ich habe eine Frage: Was ist mit konstanten flüchtigen Methoden? Wenn ich eine Klasse habe, auf die von vielen Threads zugegriffen wird (obwohl der Zugriff mit Mutex synchronisiert wird), müssen meine const-Methoden auch flüchtig sein (da einige Variablen von anderen Threads geändert werden könnten)

    – Sascha

    8. August 2012 um 23:31 Uhr

  • Eine einfache Frage: warum const volatile Objekte können niemals im Nur-Lese-Speicher platziert werden? Siehe C11, Fußnote 132.

    – pmor

    20. September um 20:04 Uhr

  • volatile teilt dem Compiler mit, den Code bezüglich der Variablen nicht zu optimieren, normalerweise wenn wir wissen, dass sie von “außen” geändert werden kann, zB durch einen anderen Thread.
  • const teilt dem Compiler mit, dass es dem Programm verboten ist, den Wert der Variablen zu ändern.
  • const volatile ist eine ganz besondere Sache, die Sie wahrscheinlich genau 0 Mal in Ihrem Leben benutzt sehen werden ™. Wie zu erwarten, bedeutet dies, dass das Programm den Wert der Variablen nicht ändern kann, aber der Wert von außen geändert werden kann, sodass keine Optimierungen an der Variablen durchgeführt werden.

  • Das hätte ich gedacht volatile Variablen sind normalerweise das, was passiert, wenn Sie anfangen, mit Hardware herumzuspielen, nicht mit anderen Threads. Wo ich gesehen habe const volatile verwendet wird in Dingen wie speicherabgebildeten Statusregistern oder ähnlichem.

    – NUR MEINE richtige MEINUNG

    4. Januar 2011 um 12:33 Uhr

  • Du hast natürlich vollkommen Recht, Multithreading ist nur ein Beispiel, aber nicht das einzige :).

    – Mingos

    4. Januar 2011 um 15:16 Uhr

  • Wenn Sie mit eingebetteten Systemen arbeiten, werden Sie dies sehr oft sehen.

    – Daniel Grillo

    11. Oktober 2013 um 12:04 Uhr

  • Es ist eigentlich nicht so besonders, ich sehe es die ganze Zeit in der eingebetteten Arbeit

    – Yvan Pearson

    8. Juli um 22:31 Uhr

Nicht weil die Variable konstant ist, kann sie sich zwischen zwei Sequenzpunkten nicht geändert haben.

Konstanz ist ein Versprechen, das Sie abgeben, den Wert nicht zu ändern, nicht, dass der Wert nicht geändert wird.

  • Plus eins für den Hinweis const Daten sind nicht “konstant”.

    – Bogdan Alexandru

    26. Januar 2015 um 7:47 Uhr


Benutzeravatar von user2903536
Benutzer2903536

In C, const und volatile sind Typqualifizierer und diese beiden sind unabhängig.

Grundsätzlich, const bedeutet, dass der Wert nicht vom Programm geändert werden kann.

Und volatile bedeutet, dass der Wert einer plötzlichen Änderung unterliegt (möglicherweise von außerhalb des Programms).

Tatsächlich gibt der C-Standard ein Beispiel für eine gültige Deklaration, die beides ist const und volatile. Das Beispiel ist:

extern const volatile int real_time_clock;

wo real_time_clock kann durch Hardware modifizierbar sein, kann aber nicht zugewiesen, inkrementiert oder dekrementiert werden.

So sollten wir schon behandeln const und volatile separat. Diese Typqualifizierer können angewendet werden struct, union, enum und typedef auch.

Ich musste dies in einer eingebetteten Anwendung verwenden, in der sich einige Konfigurationsvariablen in einem Bereich des Flash-Speichers befinden, der von einem Bootloader aktualisiert werden kann. Diese Konfigurationsvariablen sind während der Laufzeit ‘konstant’, aber ohne den flüchtigen Qualifizierer würde der Compiler so etwas optimieren …

cantx.id = 0x10<<24 | CANID<<12 | 0;

… durch Vorausberechnen des Konstantenwerts und Verwenden einer sofortigen Assembler-Anweisung oder Laden der Konstante von einem nahe gelegenen Ort, sodass alle Aktualisierungen des ursprünglichen CANID-Werts im Konfigurations-Flash-Bereich ignoriert würden. CANID muss konstant flüchtig sein.

Benutzeravatar von Vishnu CS
Vishnu CS

Sie können verwenden const und volatile zusammen. Zum Beispiel, wenn 0x30 als Wert eines Ports angenommen wird, der nur durch äußere Bedingungen geändert wird, würde die folgende Deklaration jede Möglichkeit zufälliger Nebenwirkungen ausschließen:

const volatile char *port = (const volatile char *)0x30;

const bedeutet, dass die Variable nicht durch den C-Code geändert werden kann, nicht, dass sie sich nicht ändern kann. Das bedeutet, dass keine Anweisung in die Variable schreiben kann, aber ihr Wert kann sich dennoch ändern.

volatile bedeutet, dass sich die Variable jederzeit ändern kann und somit keine zwischengespeicherten Werte verwendet werden dürfen; jeder Zugriff auf die Variable muss an deren Speicheradresse ausgeführt werden.

Da die Frage mit “eingebettet” und angenommen gekennzeichnet ist temp eine vom Benutzer deklarierte Variable ist, kein hardwarebezogenes Register (da diese normalerweise in einer separaten .h-Datei behandelt werden), beachten Sie Folgendes:

Ein eingebetteter Prozessor, der sowohl einen flüchtigen Schreib-Lese-Datenspeicher (RAM) als auch einen nichtflüchtigen Nur-Lese-Datenspeicher aufweist, beispielsweise einen FLASH-Speicher in von-Neumann-Architektur, bei dem sich Daten und Programmraum einen gemeinsamen Daten- und Adressbus teilen.

Wenn Sie erklären const temp Um einen Wert zu haben (zumindest wenn er sich von 0 unterscheidet), weist der Compiler die Variable einer Adresse im FLASH-Bereich zu, denn selbst wenn sie einer RAM-Adresse zugewiesen würde, benötigt er immer noch FLASH-Speicher, um den Anfangswert der Variablen zu speichern , was die RAM-Adresse zu einer Platzverschwendung macht, da alle Operationen schreibgeschützt sind.

Als Folge:

int temp;ist eine im RAM gespeicherte Variable, die beim Start (cstart) auf 0 initialisiert wird, zwischengespeicherte Werte können verwendet werden.

const int temp;ist eine Variable, die in (Nur-Lese-)FLASH gespeichert ist, zur Compilerzeit auf 0 initialisiert wird, zwischengespeicherte Werte können verwendet werden.

volatile int temp; ist eine im RAM gespeicherte Variable, die beim Start (cstart) auf 0 initialisiert wird, zwischengespeicherte Werte werden NICHT verwendet.

const volatile int temp; ist eine in (schreibgeschütztem) FLASH gespeicherte Variable, die zur Compilerzeit auf 0 initialisiert wird, zwischengespeicherte Werte werden NICHT verwendet

Hier kommt der nützliche Teil:

Heutzutage haben die meisten Embedded-Prozessoren die Möglichkeit, Änderungen an ihrem nichtflüchtigen Nur-Lese-Speicher mittels eines speziellen Funktionsmoduls vorzunehmen, in diesem Fall const int temp kann zur Laufzeit geändert werden, wenn auch nicht direkt. Anders gesagt, eine Funktion kann den Wert an der Adresse wo ändern temp wird gelagert.

Ein praktisches Beispiel wäre zu verwenden temp für die Seriennummer des Geräts. Wenn der eingebettete Prozessor zum ersten Mal ausgeführt wird, temp gleich 0 (oder dem deklarierten Wert) und eine Funktion kann diese Tatsache verwenden, um einen Test während der Produktion durchzuführen und bei Erfolg um die Zuweisung einer Seriennummer zu bitten und den Wert von zu ändern temp durch eine spezielle Funktion. Einige Prozessoren haben dafür einen speziellen Adressbereich mit OTP-Speicher (einmal programmierbar).

Aber hier kommt der Unterschied:

Wenn const int temp ist eine änderbare ID anstelle einer einmalig programmierbaren Seriennummer und wird NICHT deklariert volatile, kann ein zwischengespeicherter Wert bis zum nächsten Start verwendet werden, was bedeutet, dass die neue ID möglicherweise bis zum nächsten Neustart nicht gültig ist, oder noch schlimmer, einige Funktionen verwenden möglicherweise den neuen Wert, während andere bis zum Neustart einen älteren zwischengespeicherten Wert verwenden. Wenn const int temp IST erklärt voltailewird die ID-Änderung sofort wirksam.

  • Wow, diese Antwort ist lang

    Benutzer12211554

    14. Mai 2020 um 2:23 Uhr

1421270cookie-checkUnterschied zwischen const und const volatile

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy