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?
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.
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.
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)
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
intmain(intargc,char*argv[]){
5
intx,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
returny;
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:
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.