web-dev-qa-db-de.com

Warum wurde das Leerzeichen nicht für C ++ 14-Zifferntrennzeichen ausgewählt?

Ab C++ 14 können wir dank n3781 (das allein diese Frage nicht beantwortet) Code wie den folgenden schreiben:

const int x = 1'234; // one thousand two hundred and thirty four

Ziel ist es, Code wie diesen zu verbessern:

const int y = 100000000;

und lesbarer machen.

Der Unterstrich (_) wurde in C++ 11 bereits von benutzerdefinierten Literalen verwendet, und das Komma (,) hat Lokalisierungsprobleme - viele europäische Länder ratlos Verwenden Sie dies als Dezimaltrennzeichen - und widerspricht dem Kommaoperator, obwohl ich mich frage, welcher Code in der realen Welt möglicherweise kaputt gegangen sein könnte, indem er z. 1,234,567.

Eine bessere Lösung scheint jedenfalls das Leerzeichen zu sein:

const int z = 1 000 000;

Diese benachbarten numerischen Literal-Token können vom Präprozessor ebenso wie String-Literale verkettet werden:

const char x[5] = "a" "bc" "d";

Stattdessen erhalten wir den Apostroph ('), wird von keinem Schreibsystem verwendet, das mir als Zifferntrennzeichen bekannt ist.

Gibt es einen Grund, warum das Apostroph anstelle eines einfachen Leerzeichens gewählt wurde?


 Es ist verblüffend, weil alle diese Sprachen im Text den Begriff eines Kommas beibehalten, das einen ansonsten atomaren Satz "auseinanderbricht", wobei eine Periode funktioniert, um den Satz "zu beenden" - für mich ist dies zumindest ziemlich analog zu einem Komma "Auseinanderbrechen" des integralen Teils einer Zahl und einer Periode, die sie für die fraktionierte Eingabe "beenden".

Es gibt eine frühere Veröffentlichung, n3499 , die uns sagt, dass Bjarne selbst Leerzeichen als Trennzeichen vorgeschlagen hat:

Dieser Ansatz entspricht zwar einem gängigen typografischen Stil, weist jedoch einige Kompatibilitätsprobleme auf.

  • Es entspricht nicht der Syntax für eine pp-Zahl und erfordert nur eine minimale Erweiterung dieser Syntax.
  • Noch wichtiger ist, dass es eine gewisse syntaktische Mehrdeutigkeit geben würde, wenn eine hexadezimale Ziffer im Bereich [a-f] auf ein Leerzeichen folgt. Der Präprozessor würde nicht wissen, ob eine Symbolersetzung beginnend nach dem Leerzeichen durchgeführt werden soll.
  • Es würde wahrscheinlich dazu führen, dass Bearbeitungswerkzeuge, die "Wörter" erfassen, weniger zuverlässig sind.

Ich denke, das folgende Beispiel ist das Hauptproblem:

const int x = 0x123 a;

obwohl meiner Meinung nach diese Begründung ziemlich schwach ist. Ich kann mir immer noch kein reales Beispiel vorstellen, um es zu brechen.

Das Grundprinzip der "Bearbeitungswerkzeuge" ist noch schlimmer, da 1'234 unterbricht im Grunde jeden der Menschheit bekannten Syntax-Textmarker (z. B. den von Markdown in der obigen Frage selbst verwendeten!) und erschwert die Implementierung aktualisierter Versionen dieser Textmarker erheblich.

Trotzdem ist dies, egal ob gut oder schlecht, die Begründung, die stattdessen zur Annahme von Apostrophen geführt hat.

Der offensichtliche Grund dafür, dass Leerzeichen nicht verwendet werden, ist, dass eine neue Zeile ebenfalls Leerzeichen ist und dass C++ alle Leerzeichen gleich behandelt. Und natürlich kenne ich keine Sprache, die willkürliche Leerzeichen als Trennzeichen akzeptiert.

Vermutlich könnte Unicode 0xA0 (Non-Breaking Space) verwendet werden - es ist die am häufigsten verwendete Lösung beim Satz. Ich sehe jedoch zwei Probleme damit: Erstens ist es nicht im Grundzeichensatz enthalten, und zweitens ist es nicht visuell unterscheidbar. Sie können nicht erkennen, dass es sich nicht um ein Leerzeichen handelt, wenn Sie den Text in einem normalen Editor betrachten.

Darüber hinaus gibt es nicht viele Möglichkeiten. Sie können das Komma nicht verwenden, da dies bereits ein zulässiges Token ist (und so etwas wie 1,234 Ist derzeit in C++ zulässig, mit der Bedeutung 234). Und in einem Kontext, in dem dies im Gesetzbuch vorkommen könnte, z.B. a[1,234]. Obwohl ich mir keinen echten Code vorstellen kann, der dies tatsächlich verwendet, gibt es eine Grundregel, dass kein juristisches Programm, unabhängig davon, wie absurd es ist, die Semantik stillschweigend ändern sollte.

Ähnliche Überlegungen bedeuten, dass _ Ebenfalls nicht verwendet werden kann. Wenn es einen #define _234 * 2 gibt, ändert a[1_234] stillschweigend die Bedeutung des Codes.

Ich kann nicht sagen, dass ich mit der Wahl von ' Besonders zufrieden bin, aber es hat den Vorteil, dass es in Kontinentaleuropa verwendet wird, zumindest in einigen Arten von Texten. (Ich scheine mich zu erinnern, dass ich es zum Beispiel auf Deutsch gesehen habe, obwohl Deutsch im typischen Fließtext wie die meisten anderen Sprachen einen Punkt oder ein nicht unterbrechendes Leerzeichen verwendet. Aber vielleicht war es Schweizerdeutsch.) Das Problem mit ' Analysiert; Die Sequenz '1' ist bereits zulässig, ebenso wie '123'. So etwas wie 1'234 Könnte ein 1 Sein, gefolgt vom Beginn einer Zeichenkonstante. Ich bin mir nicht sicher, wie weit Sie vorausschauen müssen, um die Entscheidung zu treffen. Es gibt keine legale C++ - Sequenz, in der auf eine integrale Konstante eine Zeichenkonstante folgen kann, sodass es kein Problem gibt, legalen Code zu brechen. Dies bedeutet jedoch, dass das lexikalische Scannen plötzlich sehr kontextabhängig wird.

(In Bezug auf Ihren Kommentar: Die Wahl eines Dezimal- oder Tausendertrennzeichens ist nicht logisch. Ein Dezimaltrennzeichen zum Beispiel ist sicherlich kein Punkt. Es handelt sich lediglich um willkürliche Konventionen.)

16
James Kanze

Aus wiki haben wir ein schönes Beispiel:

auto floating_point_literal = 0.000'015'3;

Hier haben wir die . Operator und dann, wenn ein anderer Operator zu treffen wäre, würden meine Augen auf etwas Sichtbares warten, wie ein Komma oder etwas, kein Leerzeichen.

Ein Apostroph ist hier also viel besser als ein Leerzeichen.

Mit Leerzeichen wäre es

auto floating_point_literal = 0.000 015 3;

was sich nicht so richtig anfühlt wie bei den Apostrophen.


In demselben Sinne wie Albert Renshaws Antwort denke ich, dass der Apostroph klarer ist als der Raum, den die Lightness Races in Orbit vorgeben.

type a = 1'000'000'000'000'000'544'445'555;
type a = 1 000 000 000 000 000 544 445 555;

Leerzeichen werden für viele Dinge verwendet, zum Beispiel für die Verkettung der Zeichenfolgen, die im OP erwähnt werden, im Gegensatz zum Apostroph. In diesem Fall wird dies für jemanden deutlich, der verwendet wird, um die Ziffern zu trennen.

Wenn die Codezeilen zahlreicher werden, denke ich, dass dies die Lesbarkeit verbessern wird, aber ich bezweifle, dass dies der Grund ist, warum sie sich dafür entscheiden.


In Bezug auf die Leerzeichen lohnt sich ein Blick auf dieses C Frage , das besagt:

Die Sprache erlaubt kein int i = 10 000; (ein Integer-Literal ist ein Token, der dazwischenliegende Whitespace teilt es in zwei Token auf), aber es entstehen normalerweise keine oder nur geringe Kosten, wenn der Initialisierer als Ausdruck ausgedrückt wird, der eine Berechnung von Literalen darstellt:

int i = 10 * 1000; /* ten thousand */

10
gsamaras

Es ist wahr, ich sehe keine praktische Bedeutung für:

if (a == 1 1 1 1 1) ...

ziffern könnten also ohne wirkliche Mehrdeutigkeit zusammengeführt werden, aber was ist mit einer Hexadezimalzahl?

0 x 1 a B 2 3

Es gibt keine Möglichkeit, von einem Tippfehler zu unterscheiden (normalerweise sollten wir einen Fehler sehen)

9
hlide

Ich nehme an, es liegt daran, dass beim Schreiben von Code ein automatischer Zeilenumbruch (oder "Zeilenumbruch") auftritt, wenn Sie das Ende einer "Zeile" (die Breite Ihres Bildschirms) erreichen. Dies würde dazu führen, dass Ihr int in zwei Hälften geteilt wird, eine Hälfte davon in der ersten Zeile, die zweite Hälfte in der zweiten ... auf diese Weise bleibt alles im Falle eines Word-wrap.

5
Albert Renshaw
float floating_point_literal = 0.0000153;   /* C, C++*/

auto floating_point_literal = 0.0000153;    // C++11

auto floating_point_literal = 0.000'015'3;  // C++14

Das Kommentieren tut nicht weh:

/*  0. 0000 1530 */ 
float floating_point_literal = 0.00001530; 

Binäre Zeichenfolgen können schwer zu analysieren sein:

long bytecode = 0b1111011010011001; /* gcc , clang */  

long bytecode = 0b1111'0110'1001'1001;  //C++14
// 0b 1111 0110 1001 1001  would be better, really.
// It is how humans think.

Ein zu berücksichtigendes Makro:

#define B(W,X,Y,Z)    (0b##W##X##Y##Z)
#define HEX(W,X,Y,Z)  (0x##W##X##Y##Z)
#define OCT(O)        (0##O)



long z = B(1001, 1001, 1020, 1032 ); 

// result :  long z = (0b1001100110201032);

 long h = OCT( 35); 

// result :  long h  = (035); // 35_oct => 29_dec

 long h = HEX( FF, A6, 3B, D0 ); 

// result :  long h  = (0xFFA6BD0);
1
Chris Reid