Was ist die richtige Verwendung des Komma-Operators?

Lesezeit: 9 Minuten

Benutzer-Avatar
Kam

Ich habe diesen Code gesehen:

if (cond) {
    perror("an error occurred"), exit(1);
}

Warum würdest du das tun? Warum nicht einfach:

if (cond) {
    perror("an error occurred");
    exit(1);
}

  • Der Kommaoperator ist außerhalb des Ausdrucks SFINAE nutzlos.

    – Raptz

    27. Juli 2013 um 22:16 Uhr

  • Ein Komma-Operator ist manchmal nützlich in Kontexten wie dem Hauptteil eines Makros, wo Sie mehrere Operationen in einer einzigen Anweisung kombinieren möchten. Andernfalls kann es beim Inkrementieren von zwei Variablen in einer Schleife oder an einigen anderen stilisierten Stellen nützlich sein. Im Allgemeinen ist es jedoch zu vermeiden; ein Semikolon ist besser als ein Komma. Siehe auch Fragen wie Komma-Operator-Vorrang bei Verwendung mit ?: Operator für Beispiele der durch den Komma-Operator verursachten Verwirrung.

    – Jonathan Leffler

    27. Juli 2013 um 22:34 Uhr


  • @JonathanLeffler , Wir verwenden auch häufig for-Schleifen

    – Grijesh Chauhan

    28. Juli 2013 um 6:11 Uhr


  • Ich dachte, ich hätte das Komma in Schleifen mit ‘beim Inkrementieren von zwei Variablen in einer Schleife’ abgedeckt; Ich habe das Initialisieren von zwei Variablen in einer Schleife nicht ausdrücklich erwähnt, aber ich hoffte, dass dies implizit abgedeckt war (und ich hatte nicht mehr so ​​​​viel Platz im Kommentar). Ich stelle fest, dass eine Verwendung, die nicht funktioniert, ist if (check_for_error()) print_error("bust"), return -1; — was schade ist, aber es ist vollkommen koscher, wenn der Standard es ablehnt (return gibt keinen Wert an die Funktion zurück, in die er geschrieben wurde, im Gegensatz zum Aufrufen von Funktionen usw.)

    – Jonathan Leffler

    28. Juli 2013 um 6:24 Uhr

  • mögliches Duplikat von Was macht der ‘,’-Operator in C?

    – Sergej K.

    28. August 2013 um 8:01 Uhr

Benutzer-Avatar
Jongware

In Ihrem Beispiel dient es überhaupt keinem Grund. Es ist gelegentlich nützlich, wenn es geschrieben wird als

if(cond)
  perror("an error occured"), exit(1) ;

– dann nicht brauchen Geschweifte Klammern. Aber es ist eine Einladung zur Katastrophe.

Der Kommaoperator soll zwei oder mehr Ausdrücke an eine Stelle setzen, an der die Referenz nur einen erlaubt. In Ihrem Fall besteht keine Notwendigkeit, es zu verwenden; in anderen Fällen, z. B. in einer While-Schleife, kann es nützlich sein:

while (a = b, c < d)
  ...

wobei die eigentliche “Auswertung” der While-Schleife ausschließlich vom letzten Ausdruck bestimmt wird.

  • Mit anderen Worten, der Komma-Operator dient hauptsächlich der Verschleierung.

    – James Kanze

    27. Juli 2013 um 22:41 Uhr

  • Ein Kommaoperator kombiniert zwei oder mehr Ausdrückekeine Aussagen.

    – Keith Thompson

    27. Juli 2013 um 23:19 Uhr

  • @JamesKanze: Oder Makros – #define show_error(str, code) perror(str), exit(code) und dann show_error verhält sich als Funktion if (cond) show_error("an error occured", 1);. Siehe auch Antwort von Grijesh Chauhan.

    – Maciej Piechotka

    28. Juli 2013 um 7:01 Uhr


  • @MaciejPiechotka Das Makro, das Sie zeigen, verhält sich sicherlich nicht als Funktion. Zumindest in C++ (und in modernem C) sollte es als Inline-Funktion geschrieben werden, um sicherzustellen, dass es tut verhalten sich wie eine Funktion. (In älterem C würde es geschrieben werden do { if ( cond ) { char const* p = str; perror( p ); exit( code ); } while ( 0 ), um sich wie eine Funktion zu verhalten. Auch dort gibt es keinen Kommaoperator.

    – James Kanze

    28. Juli 2013 um 15:05 Uhr

Benutzer-Avatar
Billy ONeal

Legitime Fälle des Kommaoperators sind selten, aber es gibt sie. Ein Beispiel ist, wenn Sie möchten, dass innerhalb einer bedingten Bewertung etwas passiert. Zum Beispiel:

std::wstring example;
auto it = example.begin();
while (it = std::find(it, example.end(), L'\\'), it != example.end())
{
    // Do something to each backslash in `example`
}

Es kann auch an Stellen verwendet werden, an denen Sie nur einen einzigen Ausdruck platzieren können, aber möchten, dass zwei Dinge passieren. Beispielsweise erhöht die folgende Schleife x und verringert y in der dritten Komponente der for-Schleife:

int x = 0;
int y = some_number;
for(; x < y; ++x, --y)
{
    // Do something which uses a converging x and y
}

Suchen Sie nicht nach Verwendungsmöglichkeiten, aber wenn es angemessen ist, haben Sie keine Angst, es zu verwenden, und lassen Sie sich nicht aus der Fassung bringen, wenn Sie sehen, dass jemand anderes es verwendet. Wenn Sie zwei Dinge haben, die keinen Grund haben, keine separaten Anweisungen zu sein, machen Sie sie zu separaten Anweisungen, anstatt den Kommaoperator zu verwenden.

  • Billy, ist das Ergebnis eines Auftrags nicht sein neuster Wert? Da Sie neu bewerten it Unmittelbar nach der Zuweisung können Sie den Test ohne den Komma-Operator hinzufügen. (Es ist jedoch ein gültiges Beispiel.)

    – Jongware

    27. Juli 2013 um 22:23 Uhr

  • @Jongware: Ja, in diesem speziellen Fall könnten Sie das tun. Ich persönlich finde das Komma lesbarer als Zuweisungen in Bedingungen zu setzen (wegen der möglichen Verwirrung = vs. ==). Aber das ist eine Stilwahl.

    – Billy ONeal

    27. Juli 2013 um 22:24 Uhr

  • Ta. Ich versuche meistens zu vermeiden beide Konstruktionen wegen der Lesbarkeit 😉

    – Jongware

    27. Juli 2013 um 22:25 Uhr

  • @Jongware: Ja. Ungefähr das einzige Mal, dass ich das gerne sehe, ist in einer Schleife, wenn es einem erlaubt, das gesamte Iterationsmuster der Schleife in der ersten Zeile der Schleife auszudrücken. (Auf diese Weise müssen Sie nicht den gesamten Schleifenkörper durchsuchen und versuchen, einem komplexeren Iterationsmuster zu folgen.)

    – Billy ONeal

    27. Juli 2013 um 22:27 Uhr

  • @BillyONeal In jedem Fall haben Sie eine Nebenwirkung in einem Zustand, der vermieden werden sollte. Es ist ein gutes Beispiel dafür, wo der Kommaoperator es einfacher macht, schlechten Code zu schreiben.

    – James Kanze

    27. Juli 2013 um 22:58 Uhr

Die Hauptanwendung des Kommaoperators ist die Verschleierung; es erlaubt zwei Dinge zu tun, wo der Leser nur eines erwartet. Eine der häufigsten Anwendungen – das Hinzufügen von Nebenwirkungen zu einem Zustand – fällt in diese Kategorie. Es gibt jedoch einige Fälle, die als gültig angesehen werden könnten:

Diejenige, die verwendet wurde, um es in K&R darzustellen: Inkrementieren von zwei Variablen in a for Schleife. In modernem Code kann dies in einer Funktion wie auftreten std::transformoder std::copy, wobei ein Ausgabe-Iterator gleichzeitig mit dem Eingabe-Iterator inkrementiert wird. (Häufiger enthalten diese Funktionen natürlich eine while -Schleife, wobei die Inkremente in separaten Anweisungen am Ende der Schleife stehen. In solchen Fällen macht es keinen Sinn, statt zwei Anweisungen ein Komma zu verwenden.)

Ein weiterer Fall, der mir in den Sinn kommt, ist die Datenvalidierung von Eingabeparametern in einer Initialisierungsliste:

MyClass::MyClass( T const& param )
    : member( (validate( param ), param) )
{
}

(Das setzt voraus validate( param ) löst eine Ausnahme aus, wenn etwas nicht stimmt.) Diese Verwendung ist nicht besonders attraktiv, insbesondere da sie die zusätzlichen Klammern benötigt, aber es gibt nicht viele Alternativen.

Schließlich habe ich manchmal die Konvention gesehen:

ScopedLock( myMutex ), protectedFunction();

wodurch vermieden wird, einen Namen für die erfinden zu müssen ScopedLock. Um die Wahrheit zu sagen, ich mag es nicht, aber ich habe gesehen, dass es verwendet wird, und die Alternative, zusätzliche Klammern hinzuzufügen, um sicherzustellen, dass die ScopedLock sofort zerstört wird, ist auch nicht sehr schön.

  • Die Hauptanwendung des Kommaoperators ist die Verschleierung„– Ich glaube nicht, dass das stimmt kann auf diese Weise verwendet werden, aber es gibt viele legitime, nicht verschleierte Verwendungen. (Wenn Sie Ihre Beobachtungen auf Code beschränken, der von Anfängern geschrieben wurde, haben Sie wahrscheinlich Recht.)

    – Keith Thompson

    28. Juli 2013 um 1:01 Uhr

  • @KeithThompson Die Hauptverwendung, die ich gesehen habe, war Verschleierung. Ich gebe jedoch einige Beispiele, wo seine Verwendung gerechtfertigt sein könnte. Wobei die Alternativen nicht wirklich klarer sind als die Verwendung des Komma-Operators. Aber es wurde viel missbraucht, und die meisten Beispiele, die in den anderen Beispielen gepostet wurden, sind Missbrauch. (Interessanterweise wird es in C++ häufiger missbraucht als in C. In C++ können Sie es überladen, und alles der Verwendungen, die ich zum Überladen gesehen habe, sind Missbrauch.)

    – James Kanze

    28. Juli 2013 um 14:58 Uhr

Benutzer-Avatar
Grijesh Chauhan

An einigen Beispielen lässt sich dies besser nachvollziehen:

Zuerst:
Betrachten Sie einen Ausdruck:

   x = ++j;

Aber vorerst, wenn wir einen temporären Debug-Wert zuweisen müssen, dann können wir schreiben.

   x = DEBUG_VALUE, ++j; 

Zweite:

Komma , Operatoren werden häufig in verwendet for() -Schleife zB:

for(i = 0, j = 10; i < N; j--, i++) 
 //      ^                   ^     here we can't use ;  

Dritter:

Noch ein Beispiel (tatsächlich könnte man das interessant finden):

if (x = 16 / 4), if remainder is zero then print  x = x - 1;  
if (x = 16 / 5), if remainder is zero then print  x = x + 1;

Es kann auch in einem einzigen Schritt erfolgen;

  if(x = n / d, n % d) // == x = n / d; if(n % d)
    printf("Remainder not zero, x + 1 = %d", (x + 1));
  else
    printf("Remainder is zero,  x - 1 = %d", (x - 1));

PS: Es kann auch interessant sein zu wissen, dass die Verwendung manchmal katastrophal ist , Operator. Zum Beispiel in der Frage Strtok-Verwendung, Code funktioniert nicht, OP hat versehentlich vergessen, den Namen der Funktion zu schreiben und stattdessen zu schreiben tokens = strtok(NULL, ",'");er schrieb tokens = (NULL, ",'"); und er bekam keinen Kompilierungsfehler – aber das ist ein gültiger Ausdruck tokens = ",'"; verursachte eine Endlosschleife in seinem Programm.

Benutzer-Avatar
Pierre Fourgeaud

Der Komma-Operator ermöglicht das Gruppieren von Ausdrücken, wo einer erwartet wird.

Zum Beispiel kann es in einigen Fällen nützlich sein:

// In a loop
while ( a--, a < d ) ...

Aber in Ihrem Fall gibt es keinen Grund, es zu verwenden. Es wird verwirrend sein … das ist es …

In Ihrem Fall dient es nur dazu, geschweifte Klammern zu vermeiden:

if(cond)
    perror("an error occurred"), exit(1);

// =>
if (cond)
{
    perror("an error occurred");
    exit(1);
}

Ein Link zu einem Komma-Operator Dokumentation.

  • Ihr zweites Beispiel (int a = 4, b = 5;) ist keine Zuweisung, sondern Initialisierung; der Operator ist kein Komma-Operator (es gibt nämlich ein Komma, das die beiden Definitionen trennt).

    – Jonathan Leffler

    27. Juli 2013 um 22:25 Uhr

Benutzer-Avatar
Abhijit

Es scheint nur wenige praktische Anwendungen des Operators () zu geben.

Bjarne Stroustrup, Das Design und die Evolution von C++

Die meisten häufig verwendeten Kommas können im Wikipedia-Artikel nachgelesen werden Comma_operator#Verwendet.

Eine interessante Verwendung habe ich bei der Verwendung von herausgefunden boost::assignwo es den Operator mit Bedacht überladen hatte, damit er sich wie eine kommagetrennte Liste von Werten verhält, die an das Ende eines Vektorobjekts geschoben werden kann

#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace std;
using namespace boost::assign; // bring 'operator+=()' into scope

{
    vector<int> values;  
    values += 1,2,3,4,5,6,7,8,9; // insert values at the end of the container
}

Leider würde die obige Verwendung, die für das Prototyping beliebt war, jetzt archaisch aussehen, sobald Compiler mit der Unterstützung beginnen Einheitliche Initialisierung

Das lässt uns also zurück zu

Es scheint nur wenige praktische Anwendungen des Operators () zu geben.

Bjarne Stroustrup, Das Design und die Evolution von C++

  • Ihr zweites Beispiel (int a = 4, b = 5;) ist keine Zuweisung, sondern Initialisierung; der Operator ist kein Komma-Operator (es gibt nämlich ein Komma, das die beiden Definitionen trennt).

    – Jonathan Leffler

    27. Juli 2013 um 22:25 Uhr

Benutzer-Avatar
Josef Murariu

In Ihrem Fall ist der Kommaoperator nutzlos, da er zur Vermeidung hätte verwendet werden können Geschweifte Klammern, aber es ist nicht der Fall, da der Autor sie bereits gestellt hat. Deshalb ist es nutzlos und kann verwirrend sein.

1013010cookie-checkWas ist die richtige Verwendung des Komma-Operators?

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

Privacy policy