Was ist diese C ++ - Syntax, die einen von Klammern umgebenen Block dort platziert, wo ein Ausdruck erwartet wird?

78

Ich bin auf dieses seltsame C ++ - Programm gestoßen.

#include <iostream>
using namespace std;
int main()
{
  int a = ({int x; cin >> x; x;});
  cout << a;
}

Kann jemand erklären, was los ist? Wie heißt dieses Konstrukt?

Koshimitsu
quelle
51
es heißt "verschleiere den Code"
BЈовић
2
@VJo: Ich meine, wie heißt dieses "({})" - Konstrukt? Ist es ähnlich wie anonyme Funktionen?
Koshimitsu
1
+1 Blimey, das hatte ich noch nie gesehen. Schade, dass es GNU C / C ++ spezifisch ist ...
sehe
1
+1, sieht wenig ähnlich aus wie Lambda-Funktion :)
Iammilind
18
Ist es nur ich oder gibt es in gcc mehr bizarre Nicht-Standard-Erweiterungen als in jedem anderen Compiler?
David Heffernan

Antworten:

68

Es weist dem Benutzer einen Eingabewert zu aund druckt ihn aus. Dies geschieht mit a Statement Expression.

Anweisungsausdrücke sind gnu gcc Compiler-Erweiterungen werden von den C / C ++ - Standards nicht unterstützt. Daher ist jeder Code, der einen Anweisungsausdruck verwendet, nicht standardkonform und nicht portierbar.

IBM IBM XL C / C ++ v7.0 unterstützt auch Anweisungsausdrücke und die Dokumentation erklärt sie treffend:

Anweisungsausdrücke:

Eine zusammengesetzte Anweisung ist eine Folge von Anweisungen, die in geschweifte Klammern eingeschlossen sind. In GNU C kann eine zusammengesetzte Anweisung in Klammern als Ausdruck in a erscheinen Statement expression.

         .--------------.
         V              |
>>-(--{----statement--;-+--}--)--------------------------------><

Der Wert eines Anweisungsausdrucks ist der Wert des letzten einfachen Ausdrucks, der im gesamten Konstrukt angezeigt wird. Wenn die letzte Anweisung kein Ausdruck ist, ist das Konstrukt vom Typ void und hat keinen Wert.

Immer Kompilieren des Codes durch einen sandard in GCC Auswahl, verwenden Sie eine der Optionen -ansi, -std=c90oder -std=iso9899:1990, -std=c++03, -std=c++0x; Um alle vom Standard geforderten Diagnosen zu erhalten, sollten Sie auch angeben -pedantic(oder -pedantic-errorsob Sie möchten, dass es sich eher um Fehler als um Warnungen handelt).

Alok Speichern
quelle
56

Es ist eine GCC-Erweiterung. Kompilieren Sie Ihren Code mit dem -pedanticFlag, wenn Sie solche Dinge loswerden möchten (und das möchten Sie wirklich ).


quelle
10
Ich vermute, es hat so viele Stimmen bekommen, weil viele Menschen erleichtert waren, nachdem sie erfahren hatten, dass etwas, von dem sie noch nichts gehört oder das sie nicht benutzt hatten, sowieso nicht Standard ist.
Blagovest Buyukliev
18

Es erstellt einen Inline-Bereich, deklariert xdarin, liest ihn aus der Standardeingabe und die gesamte Anweisung wird schließlich ausgewertet x, der zugewiesen ist a.

Der Komma-Operator funktioniert ähnlich, benötigt jedoch keinen separaten Bereich. Zum Beispiel:

int x;
int a = (cin >> x, x);

würde das gleiche tun. Alle mit Kommas verbundenen Anweisungen werden nacheinander ausgeführt, und das Ergebnis des gesamten Ausdrucks wird auf den Wert des Operanden ganz rechts gesetzt.

Blagovest Buyukliev
quelle
Gibt es einen bestimmten Namen für "({})"?
Koshimitsu
@Koshimitsu: Das gibt es nicht, da es sich um eine Kombination von Operatoren handelt (wenn Sie sie so nennen möchten). Die geschweiften Klammern {} definieren in diesem Fall den Anfang ({) und das Ende (}) eines Bereichs. Die regulären Klammern dienen nur dazu, die Definition und den Rückgabewert des Bereichs zu kapseln. Ich bin mir nicht ganz sicher, ob diese regulären Klammern in diesem Fall weggelassen werden können, aber ich würde erwarten, dass dies möglich ist.
Rycul
1
@Koshimitsu: Ich bin nicht sehr vertraut mit C ++, aber in C ist es vollkommen legal und ich habe es oft benutzt.
Blagovest Buyukliev
1
@Neil: Nun, vielleicht liegt es daran, dass gcc der einzige C-Compiler ist, den ich benutze, daher bin ich irregeführt worden.
Blagovest Buyukliev
13

Ich glaube nicht, dass dies Standard C ++ ist. Es ist wahrscheinlich eine compilerspezifische Erweiterung, die es einem inneren Bereich ermöglicht, einen Wert auszuwerten.

Oliver Charlesworth
quelle
1
@ Doc: Unsinn. Das ist zunächst einmal nicht Standard C. Es wurde möglicherweise zu C ++ 0x hinzugefügt, ich weiß es nicht.
Oliver Charlesworth
13
@Doc Sie irren sich. Es ist nicht Standard C ++ und nicht Standard C. Es ist eine GCC-Erweiterung namens "Anweisungsausdruck".
Johannes Schaub - litb
Ich glaube nicht, dass es so ist. Visual Studio wird es sicherlich nicht akzeptieren.
Welpe
3
@mathepic: GCC ist anscheinend auch nicht (ohne die richtigen Optionen), daher die Frage und Verwirrung hier ...
Rubenvb