74 Stimmen

Auswirkungen der Verwendung eines Kommas anstelle eines Semikolons in C und C++

Beim Refactoring verschiedener Teile von C- und C++-Code ist mir mehrfach aufgefallen, dass zur Trennung von Anweisungen ein Komma statt eines Semikolons verwendet wird. Etwas wie dies;

int a = 0, b = 0;
a = 5, b = 5;

Wo ich erwartet hätte

int a = 0, b = 0;
a = 5; b = 5;

Ich weiß, dass C und C++ die Verwendung von Kommas zum Trennen von Anweisungen (insbesondere von Schleifenköpfen) zulassen, aber worin besteht der Unterschied zwischen diesen beiden Codeteilen, wenn überhaupt? Ich vermute, dass das Komma durch Ausschneiden und Einfügen eingefügt wurde, aber ist es ein Fehler und hat es Auswirkungen auf die Ausführung?

108voto

Frank Punkte 10276

In dem von Ihnen geposteten Code macht das keinen Unterschied. Im Allgemeinen trennt das Komma Ausdrücke genauso wie ein Semikolon. Wenn Sie jedoch das Ganze als einen Ausdruck betrachten, bedeutet der Komma-Operator, dass der Ausdruck das letzte Argument auswertet.

Hier ist ein Beispiel:

b = (3, 5);

wertet erst 3, dann 5 aus und ordnet letzteres b zu. b = 5 . Beachten Sie, dass die Klammern hier wichtig sind:

b = 3, 5;

Wird bewertet b = 3 , dann 5 und das Ergebnis des gesamten Ausdrucks ist 5, trotzdem b == 3 .

Der Komma-Operator ist vor allem in for-Schleifen hilfreich, wenn der Iterator-Code nicht aus einer einfachen i++ , aber Sie müssen mehrere Befehle ausführen. In diesem Fall funktioniert ein Semikolon nicht gut mit der for-Schleifen-Syntax.

25voto

x4u Punkte 13497

Das Komma ist ein Operator, der einen Wert zurückgibt, der immer das 2. (rechte) Argument ist, während ein Semikolon nur Anweisungen beendet. Dadurch kann der Komma-Operator innerhalb anderer Anweisungen verwendet werden oder mehrere Anweisungen zu einer einzigen verketten.

Hier wird die Funktion f(x) aufgerufen und dann x > y wird für die if-Anweisung ausgewertet.

if( y = f(x), x > y )

Ein Beispiel, wenn es nur verwendet wird, um die Notwendigkeit eines Blocks zu vermeiden

if( ... )
   x = 2, y = 3;

if( ... ) {
   x = 2;
   y = 3;
}

9voto

UncleBens Punkte 39755

Der Kommaoperator wertet alle Operanden von links nach rechts aus, und das Ergebnis ist der Wert des letzten Operanden.

Es ist vor allem in for-Schleifen nützlich, wenn Sie mehrere Aktionen im "Inkrement"-Teil durchführen wollen, z.B. (Umkehrung einer Zeichenkette)

for (int lower = 0, upper = s.size() - 1; lower < upper; ++lower, --upper)
    std::swap(s[lower], s[upper]);

Ein weiteres Beispiel, bei dem dies eine Option sein könnte (Suche nach allen Vorkommen in einer Zeichenkette):

#include <string>
#include <iostream>

int main()
{
    std::string s("abracadabra");
    size_t search_position = 0;
    size_t position = 0;

    while (position = s.find('a', search_position), position != std::string::npos) {
        std::cout << position << '\n';
        search_position = position + 1;
    }
}

Insbesondere die logische y kann für diese Bedingung nicht verwendet werden, da sowohl Null als auch Nicht-Null bedeuten kann, dass das Zeichen in der Zeichenkette gefunden wurde. Mit Komma, auf der anderen Seite, position = s.find() wird jedes Mal aufgerufen, wenn die Bedingung ausgewertet wird, aber das Ergebnis dieses Teils der Bedingung wird einfach ignoriert.

Natürlich gibt es auch andere Möglichkeiten, die Schleife zu schreiben:

while ((position = s.find('a', search_position)) != std::string::npos)

oder einfach

while (true) {
    position = s.find('a', search_position);
    if (position == std::string::npos)
        break;
    ...
}

7voto

catwalk Punkte 6028

Eine Anwendung wäre der Code für das Golfspiel:

if (x == 1) y = 2, z = 3;
if (x == 1) { y = 2; z = 3; }

Die erste Zeile ist kürzer, aber das sieht zu verwirrend aus, um in der regulären Entwicklung verwendet zu werden.

6voto

Michael Burr Punkte 320591

En Frank erwähnt Die Art und Weise, wie der Kommaoperator in Ihrem Beispiel verwendet wird, verursacht keinen Fehler. Der Komma-Operator kann aus mehreren Gründen verwirrend sein:

  • Sie wird nicht allzu oft eingesetzt, da sie nur in bestimmten Situationen notwendig ist.
  • es gibt mehrere andere syntaktische Verwendungen des Kommas, die wie ein Komma-Operator aussehen, es aber nicht sind (die Kommas, die zur Trennung von Funktionsparametern/-argumenten verwendet werden, die Kommas, die zur Trennung von Variablendeklarationen oder Initialisierungen verwendet werden)

Da er verwirrend und oft unnötig ist, sollte der Komma-Operator außer in einigen sehr speziellen Situationen vermieden werden:

  • kann es sinnvoll sein, mehrere Operationen in einem oder mehreren der folgenden Bereiche durchzuführen for steuernde Ausdrücke der Anweisung
  • er kann in Präprozessormakros verwendet werden, um mehr als einen Ausdruck in einer einzigen Anweisung auszuwerten. Dies geschieht in der Regel, um einem Makro zu ermöglichen, mehr als eine Sache zu tun und trotzdem ein einziger Ausdruck zu sein, damit das Makro an Stellen "passt", die nur einen Ausdruck zulassen.

Der Komma-Operator ist per Definition ein Hack-Operator - er dient dazu, zwei Dinge einzuhacken, von denen nur eines erlaubt ist. Er ist fast immer hässlich, aber manchmal ist er das einzige, was man hat. Und nur dann sollten Sie ihn verwenden - wenn Sie eine andere Möglichkeit haben, sollten Sie den Komma-Operator nicht verwenden.

Mir fallen spontan nicht allzu viele andere Gründe für die Verwendung des Operators ein, da man in den meisten anderen Situationen einen ähnlichen Effekt erzielen kann, indem man die Ausdrücke in separaten Anweisungen auswertet (obwohl ich sicher bin, dass jemand eine andere Verwendung nennen wird, die ich übersehen habe).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X