Wie heißt diese C ++ - Funktionalität?

82

Ich habe C ++ - Code geschrieben und fälschlicherweise den Namen einer Funktion weggelassen WSASocket. Mein Compiler hat jedoch keinen Fehler ausgelöst und my SOCKETmit dem ganzzahligen Wert 1 anstelle eines gültigen Sockets verknüpft .

Der betreffende Code hätte folgendermaßen aussehen müssen:

this->listener = WSASocket(address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

Aber stattdessen sah es so aus:

this->listener = (address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

Aus anderen Sprachen kommend, scheint dies eine Art anonymer Typ zu sein. Wie heißt das Feature, falls es sich wirklich um ein Feature handelt?

Was ist seine Aufgabe?

Es ist schwierig, danach zu suchen, wenn Sie nicht wissen, wo Sie anfangen sollen.

Michael J. Gray
quelle
3
+1, nette Frage für ein Pub-Quiz (oder eine entsetzliche Interviewfrage für Firmen, die gerne Leute einstellen, die gut in Denksportaufgaben sind).
Bathseba
8
Link zum Wikipedia-Artikel zum Komma-Operator . FWIW, eine der häufigsten Anwendungen besteht darin, zwei Nebenwirkungen in einem forSchleifen * -Iterationsausdruck , ala für (int i = 0, j = 0; i <10; ++ i, --j) zu erhalten ... `
Tony Delroy
1
@ MichaelJ.Gray Technisch gesehen liegst du falsch. Es überschreibt nicht das Verhalten. Stellen Sie sich vor: i=0;j=0;x=i++,j=6;x und j wären 6 und ich wäre sowieso 1. Wenn das Verhalten von i ++ überschrieben würde, würde es 0 bleiben. Aber jede Anweisung wird aufgerufen und nach Erreichen der ,nur alle Erweiterungen werden verworfen und der nächste Pseudosequenzpunkt wird aufgerufen. Der erste =weist also nur den Teil nach dem letzten zu, ,aber jeder Punkt wird aufgerufen. Wie auch immer: Ich verstehe nicht, warum Ihr Compiler Sie bei der Neudefinition der Funktionsdeklaration nicht warnt und stattdessen Ihren Code in etwas
anderes
5
Wenn Sie einen geeigneten Compiler mit aktivierten Warnungen verwenden, wird dieser beispielsweise vor einem solchen zwielichtigen Code gewarnt gccund g++mit der -WallOption:warning: left-hand operand of comma expression has no effect [-Wunused-value]
Sam Watkins
3
Meiner Meinung nach lautet die beste Antwort auf diese Frage "Warnungen immer aktivieren". Dann erklärt der Compiler selbst, dass ein Fehler vorliegt, und teilt Ihnen mit, was Sie getan haben. und diese Antwort wird auch viele andere Probleme für Sie lösen.
Sam Watkins

Antworten:

151

Der Kommaoperator † wertet die linke Seite aus, verwirft ihren Wert und ergibt als Ergebnis die rechte Seite. WSA_FLAG_OVERLAPPEDist 1, und das ist das Ergebnis des Ausdrucks; Alle anderen Werte werden verworfen. Es wird nie ein Socket erstellt.


† Sofern nicht überlastet. Ja, es kann überladen sein. Nein, Sie sollten es nicht überladen. Treten Sie jetzt von der Tastatur weg!

R. Martinho Fernandes
quelle
9
+1, Boost Spirit überlastet den Komma-Operator sehr effektiv, aber das ist eine sehr einsame Ausnahme von der Regel: Tu es nicht .
Bathseba
2
@Bathsheba Boost.Assign überlastet auch den Kommaoperator, aber wer verwendet das seit C ++ 11?
Rubenvb
39
Aber Sie hatten die beste Erklärung dafür, wie schrecklich das mächtige Komma sein kann. Unversöhnlich und voller Lächerlichkeit plagte es meinen Code einige Minuten lang, während es mich anstarrte, ohne sich für sein Verhalten zu schämen.
Michael J. Gray
1
@ R.MartinhoFernandes - Eigen überlastet auch den Kommaoperator sehr effektiv. In dieser SE-Frage finden Sie einige Beispiele für die Verwendung.
David Hammen
22

Der Komma-Operator macht Sinn aus Ihrem Code.

Sie stellen effektiv ein, this->listener = WSA_FLAG_OVERLAPPED;was zufällig syntaktisch gültig ist.

Bathseba
quelle
3
Nicht nur syntaktisch gültig, sondern da die Windows-API nicht typsicher ist, handelt es sich auch um eine gültige Konvertierung.
MSalters
5
@ MSalters nicht, dass POSIX in dieser Hinsicht viel besser ist
chbaker0
1
Aus diesem Grund sollten Konstruktoren, die mit einem einzelnen Argument aufgerufen werden können, explizit sein . Dann wäre ein Compilerfehler aufgetreten, und der Entwickler hätte die Möglichkeit gehabt, sich dieses bizarre Konstrukt noch einmal anzusehen.
Matthieu M.
@MSalters Nun, SOCKETist ein typedef für unsigned intund WSA_FLAG_OVERLAPPEDist ein intLiteral. Wäre das SOCKETein Synonym für int, wäre es nicht einmal eine Bekehrung .
Joker_vD
1
@ Joker_vD: In der Tat. Hätten sie es zu einem Typedef gemacht struct __socket*, hätten wir weniger Fehler. Aber es gibt einfach zu viel Code, der "weiß" SOCKETist ein integraler Bestandteil.
MSalters
21

Der Compiler wertet jeden Sequenzpunkt nacheinander in der Klammer aus und das Ergebnis ist der endgültige Ausdruck WSA_FLAG_OVERLAPPEDim Ausdruck.

Der Kommaoperator ,ist ein Sequenzpunkt in C ++. Der Ausdruck links vom Komma wird vollständig ausgewertet, bevor der Ausdruck rechts steht. Das Ergebnis ist immer der Wert rechts. Wenn Sie einen Ausdruck der Form haben (x1, x2, x3, ..., xn), ist das Ergebnis des Ausdrucks immer xn.

Sean
quelle
Nachdem Sie dort Ihre Klarstellung hinzugefügt haben, ist dies sinnvoller. Ich habe die Relevanz des Sequenzpunktproblems zunächst nicht ganz verstanden.
Michael J. Gray