namespace cpp

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


lernen:eastconst

const west oder east const?

Seit einigen Jahren tobt eine hitzige Debatte über diese Stilfrage auf den C++-Konferenzen, sogar mit Freundschafts-Armbändern! Für const-west-Anhänger sticht die Unveränderbarkeit als erstes beim Lesen heraus:

const char a = '-'; // oder
char const b = '+'; // so?

Testfrage: Was ist bei p und q konstant?

const char *p = &a;  // ??
char *const q = &a;  // ??

Die simple Erklärung lautet: const wirkt auf das unmittelbar links Davorstehende (außer wenn links nicht mehr steht, dann auf das unmittelbar rechts daneben). East-const-Verfechter brauchen die Ausnahme nicht zu erklären. Das ist für blutige Anfänger hilfreich:

char const *p = &a;  // (veränderbarer) Zeiger auf konstantes Zeichen
char *const q = &a;  // konstanter Zeiger auf (veränderbares!) Zeichen

Die Definition für qwird vom Compiler (zum Glück) nicht akzeptiert. Das hat aber nicht mit der east-west-Debatte zu tun, sondern mit der Verletzung eines Versprechens: Über den Komplizen q wäre die Änderung von c möglich. Erlaubt ist

char const *const q = &a; // äquivalent zu
const char *const q = &a;

Steigt man tiefer in C++ ein, kommen weitere Schlüsselwörter hinzu. Wohin kommen dann constexpr, static, inline, … — wild-west, far-east?

Hintergrund

Um die Regeln zu ergründen, muss man die Grammatik von C++ heranziehen. [Dan Saks Video CppCon 2019]

Die Deklaration eines Namens besteht aus zwei Teilen. Der senkrechte Strich markiert die Grenze:

             specifiers | declarator
                        |
static unsigned long int  *name;
   \       \_________/      ^     
    \        wirkt auf     / 
     \____________________/         

Specifiers dürfen in beliebiger Reihenfolge stehen. Davon gibt es zwei Sorten:

  • type-specifiers (int long unsigned const…) wirken sich auf den Typ aus.
  • non-type-specifiers (static thread_local extern mutable inline constexpr …) wirken auf den definierten Namen: eine static-Variable existiert über die gesamte Programmdauer.

Im declarator können *für Zeiger, [] für Felder und () für Funktionen und als Mittel zum Gruppieren vorkommen (in beliebig komplexen Kombinationen).

Dabei spielt const (und volatile) eine Doppelrolle. Es kann im specifier und auch im declarator hinter einem * stehen. Das ist ein Versprechen, den Zeiger nicht zu ändern., bei mehrstufigen Zeigern den unmittelbar links davor stehenden. Darin liegt der Grund für die Anfängern leichter zugängliche east-const-Regel.

Dagegen darf constexpr usw. nicht hinter dem * auftauchen. Für diese Schlüsselwörter bleibt es eine Frage des Stils, in welcher Reihenfolge sie auftauchen: int long unsigned constexpr ist unüblich…

Das Wichtigste ist, überhaupt const hinzuschreiben.

Bildquelle:https://pbs.twimg.com/media/EEwwhRmX4AEs-DV?format=jpg&name=small

lernen/eastconst.txt · Zuletzt geändert: 2020-08-06 17:17 von rrichter