Warum verwenden die Leute in C ++ so oft __ (doppelter Unterstrich)?

93

Ich habe einen Open-Source-C ++ - Code durchgesehen und festgestellt, dass im Code viele doppelte Unter-Scores verwendet wurden, hauptsächlich am Anfang von Variablennamen.

return __CYGWIN__;

Ich frage mich nur, ob es einen Grund dafür gibt, oder sind es nur einige Leute, die Stile codieren? Ich würde denken, dass ich es schwer zu lesen mache.

Nathan W.
quelle
2
Warum schwer zu lesen? Es ist hauptsächlich als Delimeter konzipiert, genau wie Anführungszeichen. Soweit ich mich erinnere, wird es hauptsächlich für eingebaute Konstanten verwendet.
Matthew Scharley
1
Nein, es ist kein Begrenzer. Die Unterstriche werden verwendet, um für die Implementierung reservierte Namen von Namen zu unterscheiden, die der Quellcode der Benutzer verwenden kann. Benutzer können dies tun #define FOO 1, müssen es jedoch nicht. #define __FOO__ 1Daher kann die Implementierung den Namen __FOO__für ihre eigenen Makros, Variablen, Funktionen usw. verwenden.
Jonathan Wakely
Ich denke, Matthew meinte, es sei stilistisch / visuell ein Delimeter, nicht funktional. Das ist eine interessante Hypothese, aber falsch angesichts dessen, was ich zuvor gelesen habe und Jonathans Antwort.
JMI MADISON

Antworten:

127

Aus der Programmierung in C ++, Regeln und Empfehlungen :

Die Verwendung von zwei Unterstrichen (`__ ') in Bezeichnern ist für den internen Gebrauch des Compilers gemäß dem ANSI-C-Standard reserviert.

Unterstriche (`_ ') werden häufig in Namen von Bibliotheksfunktionen verwendet (z. B." _main "und" _exit "). Beginnen Sie einen Bezeichner nicht mit einem Unterstrich, um Kollisionen zu vermeiden.

maccullt
quelle
1
Dieser Leitfaden sieht so aus, als ob er geschrieben wurde, bevor er namespaceeingeführt wurde.
cz
es war auch vom Imperial College London, nicht vom C ++ Standard; es kann ein guter Vorschlag sein.
Stucash
1
@cz Namespaces sind irrelevant. Ein Systemheader könnte einen Makronamen definieren, der mit einem Unterstrich beginnt, z _main.
Martinkunev
49

Wenn sie sich nicht als "Teil der Implementierung" fühlen, dh als Standardbibliotheken, sollten sie dies nicht tun.

Die Regeln sind ziemlich spezifisch und etwas detaillierter als einige andere vorgeschlagen haben.

Alle Bezeichner, die einen doppelten Unterstrich enthalten oder mit einem Unterstrich gefolgt von einem Großbuchstaben beginnen, sind für die Verwendung der Implementierung in allen Bereichen reserviert, dh sie können für Makros verwendet werden.

Darüber hinaus sind alle anderen Bezeichner, die mit einem Unterstrich beginnen (dh nicht gefolgt von einem anderen Unterstrich oder einem Großbuchstaben), für die Implementierung im globalen Bereich reserviert. Dies bedeutet, dass Sie diese Bezeichner in Ihren eigenen Namespaces oder in Klassendefinitionen verwenden können.

Aus diesem Grund verwendet Microsoft Funktionsnamen mit einem führenden Unterstrich und alles in Kleinbuchstaben für viele der wichtigsten Funktionen der Laufzeitbibliothek, die nicht Teil des C ++ - Standards sind. Es wird garantiert, dass diese Funktionsnamen weder mit Standard-C ++ - Funktionen noch mit Benutzercodefunktionen in Konflikt geraten.

CB Bailey
quelle
1
In C ++ sehe ich nur [lex.name] und für globale Namen [global.names]. Können Sie Referenzen geben? danke
a.lasram
36

Nach dem C ++ - Standard sind Bezeichner, die mit einem Unterstrich beginnen, für Bibliotheken reserviert. Bezeichner, die mit zwei Unterstrichen beginnen, sind Compiler-Anbietern vorbehalten.

James Curran
quelle
18
Mehr als das: Bezeichner , die irgendwo in ihnen einen doppelten Unterstrich enthalten, sind reserviert. 17.4.3.1.2
Steve Jessop
In C ++ sehe ich nur [lex.name] und für globale Namen [global.names]. Können Sie Referenzen geben? danke
a.lasram
10

Die vorstehenden Kommentare sind korrekt. __Symbol__ist im Allgemeinen ein magisches Token, das von Ihrem hilfreichen Compiler- (oder Präprozessor-) Anbieter bereitgestellt wird. Die vielleicht am häufigsten verwendeten sind __FILE__und __LINE__, die vom C-Präprozessor erweitert werden, um den aktuellen Dateinamen und die Zeilennummer anzugeben. Dies ist praktisch, wenn Sie einen Fehler bei der Programmzusicherung protokollieren möchten, einschließlich der Textposition des Fehlers.

Moor
quelle
8

Es ist etwas, was Sie im "normalen" Code nicht tun sollen. Dies stellt sicher, dass Compiler und Systembibliotheken Symbole definieren können, die nicht mit Ihren kollidieren.

Menkboy
quelle
5

Doppelte Unterstriche sind der Implementierung vorbehalten

Die am häufigsten gewählte Antwort zitiert Programmieren in C ++: Regeln und Empfehlungen :

"Die Verwendung von zwei Unterstrichen (` __ ') in Bezeichnern ist für den internen Gebrauch des Compilers gemäß dem ANSI-C-Standard reserviert. "

Doch nach ein paar C ++ und C - Normen gelesen hatte, war ich nicht in der Lage jede Erwähnung von Unterstrichen zu finden beschränkt ist nur der Compiler den internen Gebrauch. Die Standards sind allgemeiner und behalten doppelte Unterstriche für die Implementierung vor .

C ++

In C ++ (aktueller Arbeitsentwurf, abgerufen am 26.05.2019) heißt es in lex.name:

  • Jeder Bezeichner, der einen doppelten Unterstrich __ enthält oder mit einem Unterstrich gefolgt von einem Großbuchstaben beginnt, ist der Implementierung für jede Verwendung vorbehalten.
  • Jeder Bezeichner, der mit einem Unterstrich beginnt, ist der Implementierung zur Verwendung als Name im globalen Namespace vorbehalten.

C.

Obwohl diese Frage spezifisch für C ++ ist, habe ich relevante Abschnitte aus den C-Standards 99 und 17 zitiert:

C99 Abschnitt 7.1.3

  • Alle Bezeichner, die mit einem Unterstrich und entweder einem Großbuchstaben oder einem anderen Unterstrich beginnen, sind immer für jede Verwendung reserviert.
  • Alle Bezeichner, die mit einem Unterstrich beginnen, sind immer für die Verwendung als Bezeichner mit Dateibereich sowohl im normalen als auch im Tag-Namensraum reserviert.

C17 sagt dasselbe wie C99.

Was ist die Implementierung ?

Bei C / C ++ bezieht sich die Implementierung lose auf die festgelegten Ressourcen, die zum Erstellen einer ausführbaren Datei aus Benutzerquelldateien erforderlich sind. Das beinhaltet:

  • Präprozessor
  • Compiler
  • Linker
  • Standardbibliothek

Beispielimplementierungen

Es gibt eine Reihe verschiedener C ++ - Implementierungen, die auf Wikipedia erwähnt werden . (kein Ankerlink, Strg + f "Implementierung")

Hier ist ein Beispiel für die C / C ++ - Implementierung von Digital Mars, bei der einige Schlüsselwörter für eine ihrer Funktionen reserviert werden.

Bemerkenswerter Eimer
quelle
3

Zusätzlich zu Bibliotheken, auf die viele andere Personen geantwortet haben, benennen einige Personen auch Makros oder # define-Werte für die Verwendung mit dem Präprozessor. Dies würde die Arbeit erleichtern und möglicherweise die Umgehung von Fehlern in älteren Compilern ermöglichen.

Wie bereits erwähnt, hilft es dabei, Namenskollisionen zu verhindern und zwischen Bibliotheksvariablen und Ihren eigenen zu unterscheiden.

Sqeaky
quelle