Hallo, mal angenommen ich habe folgenden Ausdruck in einer if Abfrage: (x>0 && x<9 && x != 200) || x == 2 || (x++ == 2 && --x != 0) Vermutlich ist die vom Compiler abhängig. Was ist aber, wenn bereits die erste Klammer false liefert? Wird dann dann das x++ aus der anderen Klammer nicht mehr ausgeführt? Und was passiert, wenn mehrere x++ oder --x etc. angegeben werden innerhalb einer Klammer? Von links nach rechts? Und wenn ich folgendes schreibe bekomme ich eine Warnung "suggest parentheses around '&&' within '||'", verstehe ich. x > 0 && x < 10 || x == 100 Wie ist aber die Reihenfolge der Abarbeitung, wenn ich trotzdem keine Klammern setze?
Nein, in diesem Fall wird immer von links nach rechts ausgewertet. Deshalb kann man auch Null-Checks a la "if ( x && *x == 3 )" machen.
Klaus Kinski schrieb: > Hallo, > > mal angenommen ich habe folgenden Ausdruck in einer if Abfrage: > > (x>0 && x<9 && x != 200) || x == 2 || (x++ == 2 && --x != 0) Was soll der Scheiß? Willst du den C Obfuscation Wettbewerb gewinnen? > Wie ist aber die Reihenfolge der Abarbeitung, wenn ich trotzdem keine > Klammern setze? Gemäß C Prioritäten. Die kennt jeder Compiler. Aber bisweilen nicht jeder Programmierer, darum sollten zu besseren Lesbarkeit und Eindeutigkeit Klammern gesetzt werden. Aber Pre und Postincrements in derartigen logischen Ausdrücken sind ein NOGO!!! Auch wenn es C erlaubt!
Die Reihenfolge ist nicht compilerabhängig, sondern in C-Standard festgelegt. Die Auswertung erfolgt der Reihe nach von links nach rechts. Bei && wird die Auswertung abgebrochen, sobald ein false auftaucht. Und x und ein x++ in einem Ausdruck ist per se undefiniertes Verhalten. Oliver
Ich bin ziemlich sicher, dass alle (jedenfalls alle mir bekannten) solche Ausdrücke von links nach rechts abarbeiten und den rechten Teil auslassen, sobald das Endergebnis feststeht. Klammern können diese Reihenfolge ändern. Aber ob dieses Verhalten garantiert/spezifiziert ist, das weiß ich nicht.
Falk B. schrieb: > Aber Pre und Postincrements in > derartigen logischen Ausdrücken sind ein NOGO!!! Nö, && und || sind sequence points, d.h. die Ausführung der Pre- und Postincrements ist eindeutig definiert und daher wird der Compiler auch keine Warnung generieren. Die Klammernwarnung finde ich zu kleinlich. Der Code ließe sich aber bestimmt deutlich besser verstehbar hinschreiben.
so wie bei Punkt vor Strichrechnung hat && eine höhere Priorität als || https://de.m.wikibooks.org/wiki/C-Programmierung:_Liste_der_Operatoren_nach_Priorität
:
Bearbeitet durch User
Klaus Kinski schrieb: > Vermutlich ist die vom Compiler abhängig. Das steht im Standard. > Was ist aber, wenn bereits die > erste Klammer false liefert? Wird dann dann das x++ aus der anderen > Klammer nicht mehr ausgeführt? Wenn die erste Klammer true liefert wird die Auswertung abgebrochen, da das || dann auch true ergibt Das x++ bzw —x wird dann nicht mehr ausgeführt. Das ist die Kurzschlussregelung. Steht auch im Standard.
:
Bearbeitet durch User
Klaus Kinski schrieb: > x > 0 && x < 10 || x == 100 > > Wie ist aber die Reihenfolge der Abarbeitung, wenn ich trotzdem keine > Klammern setze? ((x > 0) && (x < 10)) || (x == 100)
Google nach "c operator precedence" https://en.cppreference.com/w/c/language/operator_precedence Hier ist das genauestens definiert
Das Bedenken hinsichtlich der Inkremente ist gerechtfertigt, da es vom Compiler abhängt, ob die Inkremente gemacht werden oder nicht. Genau deshalb sind gem. MISRA solche Konstruktionen nicht zulässig.
Jürgen W. schrieb: > Genau deshalb sind gem. MISRA solche Konstruktionen nicht zulässig. Vermutlich auch weil mans beim Review nicht versteht..? :) Und vermutlich weiß nicht mal der Autor nach ein paar Wochen was das Statement soll. Null wartbarkeit.
Jürgen W. schrieb: > Das Bedenken hinsichtlich der Inkremente ist gerechtfertigt, da es vom > Compiler abhängt, ob die Inkremente gemacht werden oder nicht. Es gibt in solchen Fällen 3 Möglichkeiten: 1. Die Inkremente müssen gemacht werden. 2. Die Inkremente dürfen nicht gemacht werden. 3. Es ist undefined behavior und es egal ob das Inkrement gemacht wird oder nicht. Welcher der drei Möglichkeiten in diesem Fall zutrifft legt der C Standard fest und die richtige Antwort wurde schon in diesem Thread genannt. > Genau deshalb sind gem. MISRA solche Konstruktionen nicht zulässig. Bist du sicher? Gibts dafür ne Quelle oder ist das deine Vermutung?
mh schrieb: >> Genau deshalb sind gem. MISRA solche Konstruktionen nicht zulässig. > Bist du sicher? Gibts dafür ne Quelle oder ist das deine Vermutung? Er nennt doch die relevante Quelle: MISRA C. >Rule 12.4 (required): The right-hand operand of a logical && or || operator shall not contain side effects.
Jemand schrieb: > mh schrieb: >>> Genau deshalb sind gem. MISRA solche Konstruktionen nicht zulässig. >> Bist du sicher? Gibts dafür ne Quelle oder ist das deine Vermutung? > > Er nennt doch die relevante Quelle: MISRA C. Naja, MISRA ist nicht der Standard sondern eine Empfehlung. Aber der gcc sagt dir eh alles:
1 | #include <stdlib.h> |
2 | #include <stdio.h> |
3 | |
4 | int main(int argc, char * argv[]) { |
5 | int x,y,z; |
6 | x = argv[1] ? atoi(argv[1]) : 1; |
7 | z = (y = x + 1) + x++; |
8 | printf("x = %d y = %d z = %d\n", x, y, z); |
9 | return y; |
10 | }
|
1 | $ gcc -Wall if.c && ./a.out |
2 | if.c: In function ‘main’: |
3 | if.c:7:22: warning: operation on ‘x’ may be undefined [-Wsequence-point] |
4 | z = (y = x + 1) + x++; |
5 | ~^~ |
6 | x = 2 y = 2 z = 3 |
D.h. der gcc warnt davor, dass entweder x++ oder die Zuweisung zu y zuerst ausgefuehrt werden koennte. "Short-circuit evaluation" ist ganz was anderes und bestimmt. leo
Jemand schrieb: > mh schrieb: >>> Genau deshalb sind gem. MISRA solche Konstruktionen nicht zulässig. >> Bist du sicher? Gibts dafür ne Quelle oder ist das deine Vermutung? > > Er nennt doch die relevante Quelle: MISRA C. > >>Rule 12.4 (required): The right-hand operand of a logical && or || operator shall > not contain side effects. Es geht mir nicht um die Regel selbst, sondern um die Rechtfertigung der Regel, das "Genau deshalb". leo schrieb: > D.h. der gcc warnt davor, dass entweder x++ oder die Zuweisung zu y > zuerst ausgefuehrt werden koennte. Das ist aber ein neues Beispiel und hat nichts mit dem Rest des Threads zu tun.
mh schrieb: > Das ist aber ein neues Beispiel und hat nichts mit dem Rest des Threads > zu tun. Aber nein, das behandelt nur deinen 3. Fall und verdeutlicht vom TO:
1 | ... (x++ == 2 && --x != 0) |
leo
leo schrieb: > mh schrieb: >> Das ist aber ein neues Beispiel und hat nichts mit dem Rest des Threads >> zu tun. > > Aber nein, das behandelt nur deinen 3. Fall und verdeutlicht vom TO: ... > (x++ == 2 && --x != 0) > > leo Ich verstehe nicht was du meinst. Das Beispiel vom TO ist "OK", also nach dem C Standard ist das Verhalten definiert. Dein Beispiel ist einfach UB.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.