Das ist eine rein theoretische Frage zum C-Standard, ohne praktischen
Bezug.
Folgender Sachverhalt:
Ein Compiler darf grundsätzlich keine Funktionsaufrufe wegoptimieren
(Attribute wie "pure" mal nicht betrachtet).
1
voidfoo()
2
{
3
inti;
4
i=bar();
5
i=bar();
6
printf("%i",i);
7
}
Deswegen muss bar() hier wirklich zweimal aufgerufen werden.
Grund ist, dass Funktionen ja auch Nebeneffekte haben können. bar()
könnte z.B. jedesmal einen Zähler inkrementieren von dem der Compiler
nichts weiß.
Nächstes Beispiel:
1
if((foo()==1)&&(bar()==2))
2
{
3
...
4
}
5
else
6
{
7
...
8
}
Hier darf der Compiler, sollte die erste Teilbedingung fehlschlagen,
gleich in den else-Pfad springen. Bedingung 2 muss nicht mehr evaluiert
werden.
Dadurch könnte der Aufruf von bar() aber verloren gehen!
Für mich ist das ein wenig widersprüchlich. Beispiel 1 zeigt, dass sich
die Schöpfer des Standards sehr wohl Gedanken über Nebeneffekte gemacht
haben.
Aber anscheinend nicht konsequent genug, wie Beispiel 2 zeigt.
Ist das einfach wieder so eine historisch gewachsene Altlast?
Oder gibt es einen praktischen Grund für diesen Widerspruch?
Na, Du sagst selbst, dass Funktionsaufrufe nicht wegoptimiert werden.
Damit kann ist die zweite Bedingung nicht wegoptimiert werden, hier ist
also kein "short evaluation" möglich.
Michl schrieb:> Oder gibt es einen praktischen Grund für diesen Widerspruch?
Ja, das ist so gewollt.
Z.B. man prüft erst einen Pointer und schreibt dann darauf.
Ist der Pointer ungültig, kann man ja nicht einfach ins Nirwana
schreiben und den RAM zerstören. Und genau das verhindert das "&&".
Will man aber immer beide Ausdrücke ausführen, nimmt man eben das
einfache "&".
@Michl (Gast)
>Grund ist, dass Funktionen ja auch Nebeneffekte haben können.
Ja.
>bar()>könnte z.B. jedesmal einen Zähler inkrementieren von dem der Compiler>nichts weiß.
Richtig.
>Hier darf der Compiler, sollte die erste Teilbedingung fehlschlagen,>gleich in den else-Pfad springen. Bedingung 2 muss nicht mehr evaluiert>werden.
Nennt sich short circuit evaluation.
>Dadurch könnte der Aufruf von bar() aber verloren gehen!
Ja.
>Für mich ist das ein wenig widersprüchlich.
Nein, das ist C ;-)
Wenn man es sauber machen will, macht man in logischen Ausfrücken im
if() keine Funktionsaufrufe, welche AKTIVE Veränderungen erzeugen. Rein
passive Berechnungen, welche NUR Lesezugriffe enthalten, sind
unkritisch.
Das steht auch in jedem guten C-Lehrbuch drin.
>Aber anscheinend nicht konsequent genug, wie Beispiel 2 zeigt.
Keine Ahnung. Ein Hammer hat auch den Nebeneffekt, dass wenn man ihn auf
den Fuß fallen läßt, es weh tut.
Peter Dannegger schrieb:> Will man aber immer beide Ausdrücke ausführen, nimmt man eben das> einfache "&".
Nun ja, daß ist mal wieder einer der klassischen Peter-Hacks. Wildes
Bit-Geschubse, um am Ende eine Zeile Sourcecode zu sparen.
Will man beide Funktionen ausführen, dann schreibt man das einfach hin:
Michl schrieb:> Ein Compiler darf grundsätzlich keine Funktionsaufrufe wegoptimieren
Dem Compiler ist egal, was Du denkst. Manche default Einstellungen
machen durchaus unerwartetes.
Z.B. beim AVR-GCC kann er default Funktionen inlinen, von denen er
denkt, sie seien kurz. Und dann kann er wegoptimieren, was seiner
Meinung nach keinen Effekt hat.
Ein Funktionsaufruf ist also keine Garantie für einen Sequence-Point.
http://stackoverflow.com/questions/1474030/how-can-i-tell-gcc-not-to-inline-a-function
Michl schrieb:> i = bar();> i = bar();> ...>> Deswegen muss bar() hier wirklich zweimal aufgerufen werden.
Er muss nicht unbedingt. Wenn er die Definition von bar kennt und
deswegen sicherstellen kann, dass der zweite Aufruf keine Nebeneffekte
hat, darf er diesen auch weglassen.
> if ( (foo() == 1) && (bar() == 2) )>> Hier darf der Compiler, sollte die erste Teilbedingung fehlschlagen,> gleich in den else-Pfad springen.
Er muss sogar, selbst dann, wenn bar Nebeneffekte haben sollte. Das
ist im Standard so vorgegeben. Die Zeile ist äquivalent zu
1
if(foo()==1)
2
if(bar()==2)
Hier wird bar auch nur dann aufgerufen, wenn die erste Bedingung
erfüllt ist.
> Ist das einfach wieder so eine historisch gewachsene Altlast?
Diese so genannte short-cut evaluation ist nicht gewachsen, sondern
volle Absicht und wird auch in vielen anderen Programmiersprachen
verwendet. Das dient nicht nur der Code-Optimierung, sondern auch dazu,
Dinge wie das folgende schreiben zur können:
1
if(x!=0&&func(1/x)<10)
Durch die Bedingung links von && ist garantiert, dass im Ausdruck rechts
nie durch 0 dividiert wird.
Oliver S. schrieb:> Nun ja, daß ist mal wieder einer der klassischen Peter-Hacks. Wildes> Bit-Geschubse, um am Ende eine Zeile Sourcecode zu sparen.
Hä?
Er soll nur das eine "&" weglasssen und schon stimmts.
Von Bitschubsen war nie die Rede.
Es gibt allerdings noch einen feinen Unterschied zwischen "&&" und "&":
Das "&&" evaluiert alle Ausdrücke != 0.
Das "&" erfordert, daß beide Ausdrücke ein gleiches Bit gesetzt haben
müssen, z.B. "1" ergeben, was ja bei "x==y" der Fall ist.
@ Peter Dannegger (peda)
>> Oder gibt es einen praktischen Grund für diesen Widerspruch?>Ja, das ist so gewollt.
Naja, da bin ich mir nicht so sicher. Es ist DA, aber ob das wirklich
Absicht war? Oder vielmehr, "ist halt so, muss man aufpassen"?
>Z.B. man prüft erst einen Pointer und schreibt dann darauf.>Ist der Pointer ungültig, kann man ja nicht einfach ins Nirwana>schreiben und den RAM zerstören. Und genau das verhindert das "&&".
Das hat mit dem gezeigten Problem wenig zu tun.
>Will man aber immer beide Ausdrücke ausführen, nimmt man eben das>einfache "&".
Auch das ist nur in Fällen möglich, wo die Funktionen ECHTE Bools zurück
leifern, denn ein logisches Und ist nicht identisch mit einem binären
Und. Und in einigen Fällen geht das ordentlich schief!
Und so weiter ;-)
Man macht sinnvollerweise KEINERLEI Funktionsaufrufe mit Nebeneffekten
im if() oder while() oder ähnlichen Konstrukten, welche short circuit
evaluation bieten. Und wenn man nicht genau weiß, ob die Funktion sicher
ist oder nicht, muss man sie schlicht aus der Abfrage rausnehmen und als
normale Funktion mit Rückgabewert behandeln, und dann diesen
Rückgabewert auswerten. Man muss nicht jeden Wahnsinn den C bietet auch
im echten Programmiererleben mitmachen.
Huch, ich sehe gerade, dass short circuit evaluation auch bei ganz
normalen Ausdrücken mit && und || gemacht werden kann.
http://de.mathworks.com/help/matlab/ref/logicaloperatorsshortcircuit.html
DAS ist allerdings gefährlich, wenn man solche Sachen macht. Was meinen
die C-Experten? Gibt es Compileroptionen, um das auszuschalten?
Es ist zwar durchaus nicht fernliegend, die Angelegenheit so zu
betrachten, als wenn K&R "sich nicht genug Gedanken gemacht haben", aber
das trifft doch nicht wirklich zu. Denn das tatsächliche Verhalten ist
einerseits durchaus definiert und andererseits (sehr wahrscheinlich)
gewollt.
Man kann nämlich durch die Wahl der Reihenfolge der (beiden oder mehr)
Teilausdrücke das Verhalten präzise kontrollieren. Das liegt an den sog.
"Sequence Points". (http://en.wikipedia.org/wiki/Sequence_point) die
dafür sorgen, dass der erste Ausdruck auf jeden Fall auch zuerst
vollständig ausgewertet wird. Wenn man das berücksichtigt, sind die
Verhältnisse durchaus klargestellt.
Ohne das gesagte eigentlich relativieren zu wollen, muss man allerdings
einräumen, dass Fälle denkbar sind, in denen zwei Funktionen in einer
gewissen Reihenfolge aufgerufen werden müssen - und zwar einmal ohne
Berücksichtigung des Resultats - und das andere Mal um deren
Resultatwert auszuwerten. Wenn dann die zweite Funktion einen
Nebeneffekt hat, der zwingend eintreten soll, dann geht das in
Bedingungen nicht. Soweit ist der Gedankengang sinnvoll.
Dann stellt sich allerdings die Frage ob man entweder, wie P.D. anregte,
den '&'-Operator verwenden sollte oder die Funktionen in einer dritten
vereinigt.
@Oliver S. (oliverso)
>Nun ja, daß ist mal wieder einer der klassischen Peter-Hacks. Wildes>Bit-Geschubse, um am Ende eine Zeile Sourcecode zu sparen.
Hehe, zwei Dumme, ein Gedanke ;-)
>Will man beide Funktionen ausführen, dann schreibt man das einfach hin:>bool bfoo = (foo() == 1);>bool bbar = (bar() == 2);
Jain, dann dazu braucht man für jede Funktion wieder ein Makro. Nicht
sehr schön und praxistauglich.
Yalu X. schrieb:> Das dient nicht nur der Code-Optimierung, sondern auch dazu,> Dinge wie das folgende schreiben zur können:
Oder sowas:
1
if(ptr&&*ptr!='\0')...
Das sind Dinge, die man bspw. in Pascal nicht so schreiben konnte,
weil der Sprachstandard den „Kurzschluss“ dort eben nicht vorgeschrieben
hat, sondern (meiner Erinnerung nach) dem Compilerbauer überlassen hat.
Falk Brunner schrieb:> Man macht sinnvollerweise KEINERLEI Funktionsaufrufe mit Nebeneffekten> im if() oder while() oder ähnlichen Konstrukten, welche short circuit> evaluation bieten.
Es sei denn genau das ist gewollt.
> Huch, ich sehe gerade, dass short circuit evaluation auch bei ganz> normalen Ausdrücken mit && und || gemacht werden kann.
Nicht kann_ sondern _muss
Die Sprache ist so definiert.
Falk Brunner schrieb:> Gibt es Compileroptionen, um das auszuschalten?
Ja.
Einfach das "||" und "&&" nicht mehr benutzen.
Sondern nur noch "|" und "&" auf logische Ausdrücke.
Falk Brunner schrieb:> Huch, ich sehe gerade, dass short circuit evaluation auch bei ganz> normalen Ausdrücken mit && und || gemacht werden kann.
C kennt keine "normalen Ausdrücke", jeder Ausdruck hat einen Wert.
Und jeder Wert kann
- einen anderen Ausdruck bedingt ausführen,
- Operand eines weiteren Ausdrucks sein,
- einer Variable zugewiesen werden,
- ein Returnwert sein oder
- ignoriert werden.
Michl schrieb:> Das ist eine rein theoretische Frage zum C-Standard, ohne praktischen> Bezug.>> Folgender Sachverhalt:> Ein Compiler darf grundsätzlich keine Funktionsaufrufe wegoptimieren
Die Aussage ist so nicht haltbar. Das ist etwas zu vereinfacht
ausgedrückt.
Natürlich darf ein Compiler Funktionsaufrufe wegoptimieren. In
1
inti=5;
2
if(i==8)
3
bar();
darf der Aufruf selbstverständlich wegoptimiert werden.
Dein Kopfzerbrechen rührt daher, dass die Original-Aussage mit ihrem
'grundsätzlich' nicht korrekt ist.
Funktionsaufrufe sind in der Beziehung auch nicht anders als alles
andere: Der Compiler darf optimieren, solange das beobachtbare Ergebnis
sich nicht unterscheidet. Bei einem Funktionsaufruf, bei dem der
Compiler den Inhalt der Funktion nicht kennt, wird er sich eben schwer
tun, genau diese Nichtveränderung nachzuweisen.
Und ja: für && und || ist die Short Circuit Evaluation vorgeschrieben.
Die muss er machen und du als Progammierer bist verpflichtet das zu
wissen.
Karl Heinz schrieb:>> Ein Compiler darf grundsätzlich keine Funktionsaufrufe wegoptimieren>> Die Aussage ist so nicht haltbar. Das ist etwas zu vereinfacht> ausgedrückt.
Die Aussage ist nicht vereinfacht, sondern falsch. Wenn der Compiler den
Code der aufgerufenen Funktion kennt, dann stehen ihm alle Möglichkeiten
offen. Das kann der Fall sein, wenn der Code im gleichen File steht,
oder wenn zwecks Optimierung nicht einzeln sondern alles zusammen
übersetzt wird.
Der Compiler darf einen Funktionsaufruf so betrachten, als wenn an
dieser Stelle der Code der aufgerufenen Funktion direkt stünde. Was dann
dabei rauskommt ergibt sich aus den üblichen Regeln. Ein Funktionsaufruf
ändert daran nichts.
Dass es ein Aufruf der Praxis oft auch umgesetzt wird liegt daran, dass
über den Inhalt von Funktionen oft nichts bekannt ist. Aber das kann
sich mit einer neuen Version eines Compilers, der nicht mehr einzeln
übersetzt, sondern stets alles zusammen, urplötzlich ändern.
> Deswegen muss bar() hier wirklich zweimal aufgerufen werden.
Nein. Zuallererst einmal wird die Funktion 2 mal aufgerufen, weil da 2
Funktionsaufrufe stehen. Optimierungen sind da überhaupt noch nicht im
Spiel.
> Grund ist, dass Funktionen ja auch Nebeneffekte haben können.
Nein. Der Grund ist, weil in der Konstellation der Compiler nicht
feststellen kann, ob sich das Ergebnis unterscheiden wird, wenn einer
der Aufrufe nicht erfolgt. Kenn er dieses nicht feststellen, dann kann
er auch nicht optimieren.
Oberste Direktive in der Optimierung ist immer die 'as if' Regel. Der
Compiler darf optimieren, solange sich das beobachtete Ergebnis
(umgangssprachlich 'die Endergebnisse') nicht von dem unterscheidet, was
ohne Optimierung entstanden wäre. Eben 'as if' die Optimierung nicht
stattgefunden hätte.
Kann er das nicht, dann ist der Code so zu übersetzen, wie er dort steht
und was die C Regeln über die Interpretation des hingeschriebenen
aussagen.
A. K. schrieb:> Karl Heinz schrieb:>>> Ein Compiler darf grundsätzlich keine Funktionsaufrufe wegoptimieren>>>> Die Aussage ist so nicht haltbar. Das ist etwas zu vereinfacht>> ausgedrückt.>> Die Aussage ist nicht vereinfacht, sondern falsch.
Ich wollte nicht gleich mit der Tür ins Haus fallen.
Michl schrieb:> if ( (foo() == 1) && (bar() == 2) )
Der rechte Funktionsaufruf wird genau genommen nicht wegoptimiert. Der
Sprung in die Fkt steht immer noch HEX/exe File, wird aber nur bedingt
ausgeführt (short circuit evaluation).
Karl Heinz schrieb:>> Grund ist, dass Funktionen ja auch Nebeneffekte haben können.> Nein. Der Grund ist, weil in der Konstellation der Compiler nicht> feststellen kann, ob sich das Ergebnis unterscheiden wird, wenn einer> der Aufrufe nicht erfolgt. Kenn er dieses nicht feststellen, dann kann> er auch nicht optimieren.
Mit den GCC Attributen "const" und "pure" kann man angeben, inwieweit
Nebeneffekte auftreten können oder Funktionen vom globalen Kontext
abhängen.
Eine mit "const" attributierte Funktion liefert unabhängig von jedem
Kontext immer das gleiche Ergebnis und hat keine Nebeneffekte. Eine
solche Funktion kann jederzeit wegoptimiert werden, wenn das Ergebnis
nicht benötigt wird.
Bei "pure" kann lesender Zugriff auf globale Variablen auftreten,
weshalb sie nur verschwinden können, wenn der Compiler weiss, dass sich
die aus seiner Sicht nicht geändert haben können.
Das ist aber nur eine Optimierungshilfe. Wenn der Compiler den Code
einer Funktion kennt, dann kann er das alles auch selber rauskriegen.
C-liker schrieb:> Michl schrieb:>> if ( (foo() == 1) && (bar() == 2) )> Der rechte Funktionsaufruf wird genau genommen nicht wegoptimiert.
... ausser wenn der Compiler weiss, dass foo() nie 1 wird. ;-)
A. K. schrieb:> Mit den GCC Attributen "const" und "pure" kann man angeben,
Was jetzt, da wie hier im gcc-Forum sind, zutreffend ist. Der TO bezieht
sich aber auf den C-Standard, und der kennt weder const noch pure.
Oliver
Peter Dannegger schrieb:> Will man aber immer beide Ausdrücke ausführen, nimmt man eben das> einfache "&".
Keine gute Idee, denn die Reihenfolge der Auswertung ist nicht vom
Standard festgelegt.
Wenn also foo und bar Nebeneffakte haben, wie es mein TO ja der Fall
ist, dann kann das Ergebnis der Auswertung von der Reihenfolge abhängen.
Beispiel: bar macht ein Var++ und foo ein Var=0.
@Johann L. (gjlayde) Benutzerseite
>Wenn also foo und bar Nebeneffakte haben, wie es mein TO ja der Fall>ist, dann kann das Ergebnis der Auswertung von der Reihenfolge abhängen.>Beispiel: bar macht ein Var++ und foo ein Var=0.
Dann MUSS man so oder so die Funktionen einzeln aufrufen. Richtig?
Falk Brunner schrieb:> @Johann L. (gjlayde) Benutzerseite>>>>Wenn also foo und bar Nebeneffakte haben, wie es mein TO ja der Fall>>ist, dann kann das Ergebnis der Auswertung von der Reihenfolge abhängen.>>>Beispiel: bar macht ein Var++ und foo ein Var=0.>> Dann MUSS man so oder so die Funktionen einzeln aufrufen. Richtig?
Genau.
Falk Brunner schrieb:> @ Peter Dannegger (peda)>>>> Oder gibt es einen praktischen Grund für diesen Widerspruch?>>>Ja, das ist so gewollt.>> Naja, da bin ich mir nicht so sicher. Es ist DA, aber ob das wirklich> Absicht war? Oder vielmehr, "ist halt so, muss man aufpassen"?
Du meinst, es wurde nur versehentlich explizit so in die
ISO-C-Definition reingeschrieben?
Falk Brunner schrieb:>>Z.B. man prüft erst einen Pointer und schreibt dann darauf.>>Ist der Pointer ungültig, kann man ja nicht einfach ins Nirwana>>schreiben und den RAM zerstören. Und genau das verhindert das "&&".>> Das hat mit dem gezeigten Problem wenig zu tun.
Das gezeigte ist kein Problem, und natürlich hat das mit einander zu
tun. Es ist in C festgelegt, daß bei && der rechte Operand nicht
ausgewertet werden darf, wenn der linke den Wert 0 hat. Ob da jetzt
links ein Zeigervergleich und rechts dessen Dereferenzierung oder auf
beiden Seiten Funktionsaufrufe stehen, macht in der Hinsicht keinen
Unterschied.
Falk Brunner schrieb:> Man macht sinnvollerweise KEINERLEI Funktionsaufrufe mit Nebeneffekten> im if() oder while() oder ähnlichen Konstrukten, welche short circuit> evaluation bieten.
Weder if noch while bietet shortcut evaluation.
Falk Brunner schrieb:> Huch, ich sehe gerade, dass short circuit evaluation auch bei ganz> normalen Ausdrücken mit && und || gemacht werden kann.
Es kann nicht nur, sondern muß gemacht werden, und das bei jedem && und
||, ganz egal, wo du es verwendest. Statt
1
inta();
2
intb();
3
4
if(a())
5
b();
könnte ich auch schreiben:
1
inta();
2
intb();
3
4
a()&&b();
> DAS ist allerdings gefährlich, wenn man solche Sachen macht.
Was ist daran gefährlich? Und warum sollte es außerhalb eines if
gefährlicher sein, als im if?
> Was meinen die C-Experten? Gibt es Compileroptionen, um das> auszuschalten?
Glaube ich nicht.
Rolf Magnus schrieb:>> Was meinen die C-Experten? Gibt es Compileroptionen, um das>> auszuschalten?>> Glaube ich nicht.
"Kurzschlußauswertung" ist ein zentrales Sprachelement von C.
Wär' schon komisch, wenn man Dinge, mit denen man nicht zurechtkommt,
selektiv ausschalten könnte. Pointer, zum Beispiel.
Markus F. schrieb:> Rolf Magnus schrieb:>>> Was meinen die C-Experten? Gibt es Compileroptionen, um das>>> auszuschalten?>>>> Glaube ich nicht.>> "Kurzschlußauswertung" ist ein zentrales Sprachelement von C.>> Wär' schon komisch, wenn man Dinge, mit denen man nicht zurechtkommt,> selektiv ausschalten könnte. Pointer, zum Beispiel.
LOL
Erzähl das mal der MISRA
http://de.wikipedia.org/wiki/MISRA-C
1
MISRA-C ist ein C-Programmierstandard aus der Automobilindustrie, der von
2
der englischen MISRA (Motor Industry Software Reliability Association)
3
erarbeitet wurde. Der MISRA-C-Programmierstandard definiert eine Untermenge
4
des Sprachumfangs von C, d.h. er umfasst Richtlinien die zu einer
5
Qualitätssteigerung (insbesondere der Softwarequalitätsaspekte der
6
Zuverlässigkeit und Wartbarkeit) in der Software-Entwicklung führen sollen.
Ich hab ja immer gedacht, dass Leute die ihre Sprache beherrschen und
Erfahrung haben den größten Qualitätsboost bringen, aber scheinbar gibt
es da auch andere Ansichten.
@ Rolf Magnus (rmagnus)
>> Naja, da bin ich mir nicht so sicher. Es ist DA, aber ob das wirklich>> Absicht war? Oder vielmehr, "ist halt so, muss man aufpassen"?>Du meinst, es wurde nur versehentlich explizit so in die>ISO-C-Definition reingeschrieben?
Nein. Ich wußte es schlicht nicht.
>tun. Es ist in C festgelegt, daß bei && der rechte Operand nicht>ausgewertet werden darf, wenn der linke den Wert 0 hat.
OK, wieder was gelernt.
>Weder if noch while bietet shortcut evaluation.
Jaja, mein Fehler. Bin kein C-Profi.
Falk Brunner schrieb:
> Huch, ich sehe gerade, dass short circuit evaluation auch bei ganz> normalen Ausdrücken mit && und || gemacht werden kann.>int a();>int b();> a() && b();>> DAS ist allerdings gefährlich, wenn man solche Sachen macht.>Was ist daran gefährlich?
Der unbedarfte Betrachter, so wie ich, würde nicht erwarten, dass b()
nur in Abhängigkeit des Ergebnisses von a() ausgeführt wird. Diese
Spitzfindigkeiten machen C gefährlich und werden zu Recht kritisiert.
http://computer-programming-forum.com/47-c-language/f00e905102413f96.htm
Jaja, ist nur ein Kommentar von Millionen im Netz.
> Und warum sollte es außerhalb eines if>gefährlicher sein, als im if?
Im if() ist es eindeutig, EXPLIZIT sichtbar, was wann passiert, in der
Short circuit evaluation ist es IMPLIZIT und damit bisweilen gut
versteckt.
Das Kommutativgesetz gilt hier NICHT!
>> Was meinen die C-Experten? Gibt es Compileroptionen, um das>> auszuschalten?>Glaube ich nicht.
Hab ich nun auch kapiert, es ist elementarer Bestandteil von C.
Macht die Sache aber nicht schöner. Welchen großen Vorteil hat es, das
so implizit zu schreiben, anstatt explizit in geschachtelten if()?
Aussern beim
The International Obfuscated C Code Contest
gewinnt man da keine Blumentöpfe, nur weil man ne handvoll Zeichen
einsparen kann. Pascal rulez! ;-)
Falk Brunner schrieb:> Hab ich nun auch kapiert, es ist elementarer Bestandteil von C.> Macht die Sache aber nicht schöner. Welchen großen Vorteil hat es, das> so implizit zu schreiben, anstatt explizit in geschachtelten if()?
Nochmal, das hat mit dem if nicht das geringste zu tun.
Die Short Circuit Evaluation ist Eigenschaft der Operatoren && und ||.
Es ist nur so, dass diese Operatoren naturgemäss am häufigsten in if
oder while oder for Anweisungen auftauchen.
Irgendwo weiter oben hat schon mal wer, ich glaub es war Jörg
aufgezeigt, das die Nicht-Festlegung der Short Circuit Evaluation sich
als pain in the ass erwiesen hat.
Im Urpascal musste man alle Pointer Zugriffe die man absichern wollte so
schreiben (ich verwende C Syntax, weil mein Pascal schon eingerostet
ist)
1
if(p)
2
if(*p)
Man konnte sich nie sicher sein, ob ein spezieller Pascal Compiler Short
Circuit machen wird oder nicht. Da solche Dinge aber in einem normalen
Programm in der Größenordnung von ein paar Zehntausend mal vorkommt, ist
das ein 'pain in the ass', wenn man das jedesmal ausschreiben muss. Ganz
zu schweigen von den Schachtelungstiefen, die da ganz schnell anwachsen.
1
if(pAND*p)
konnte man nicht benutzen. Dieser Fall kommt aber häufig vor!
Karl Heinz schrieb:> Ich hab ja immer gedacht, dass Leute die ihre Sprache beherrschen und> Erfahrung haben den größten Qualitätsboost bringen, aber scheinbar gibt> es da auch andere Ansichten.
Für die ist MISRA ja nicht gedacht, sondern für die Manager, die ja auch
irgendwie das Gefühl haben müssen, irgendwas für die Codequalität getan
zu haben. Dieses Gefühl können sie bekommen, indem sie MISRA-C
verordnen.
Tatsächlich ist das aber natürlich ein Papiertiger. Wer schlechten Code
schreibt, wird durch MISA nicht auf einmal zum Programmiergott. Und wer
sich mit C wirklich auskennt, kriegt das auch ohne MIRSA hin.
Falk Brunner schrieb:> Der unbedarfte Betrachter, so wie ich, würde nicht erwarten, dass b()> nur in Abhängigkeit des Ergebnisses von a() ausgeführt wird. Diese> Spitzfindigkeiten machen C gefährlich und werden zu Recht kritisiert.
Also da fallen mir erhlich gesagt viele andere Dinge in C ein, die viel
schlimmer sind. Letztendlich macht das aber auch den Unterschied
zwischen dem, der damit halt mal ein bischen rumgespielt hat und dem,
der die Sprache vernünftig gelernt hat. Letzterer kennt solche Details.
Wer nicht weiß, an welcher Seite er den Lötkolben anfassen muss,
verbrennt sich halt unter Umständen auch mal die Finger. ;-)
>> Und warum sollte es außerhalb eines if>>gefährlicher sein, als im if?>> Im if() ist es eindeutig, EXPLIZIT sichtbar, was wann passiert, in der> Short circuit evaluation ist es IMPLIZIT und damit bisweilen gut> versteckt.
Was sollte an
1
if(a&&b)
eindeutiger als bei
1
x=a&&b;
sein? Für mich ist da kein Unterschied.
> Hab ich nun auch kapiert, es ist elementarer Bestandteil von C.> Macht die Sache aber nicht schöner. Welchen großen Vorteil hat es, das> so implizit zu schreiben, anstatt explizit in geschachtelten if()?
Ich finde ein
1
if(p&&q&&p->wert==q->wert)
2
{
3
// tuwas
4
}
schöner als ein
1
if(p)
2
{
3
if(q)
4
{
5
if(p->wert==q->wert)
6
{
7
// tuwas
8
}
9
}
10
}
Und letztendlich ist es zwar eigentlich keine Optimierung im Sinne eines
Compiler-Optimizers, aber mit eine der Ideen dahinter ist durchaus, daß
man sich die Auswertung der rechten Seite ja sparen kann, wenn die am
Ergebnis nichts mehr ändern kann. Wenn ich also z.B. zwei sehr
aufwendige Funktionen aufrufe, die irgendwelche Bedingungen prüfe, muß
ich je nach Ergebnis der ersten die zweite gar nicht mehr aufrufen, weil
das Gesamtergebnis schon bekannt ist. Klar könnte man das auch mit
verschachtelten ifs lösen, aber das wird meines Erachtens nicht
automatisch immer lesbarer sein.
Ich kann ja auch umgekehrt sagen, daß man, wenn beide Seiten zwingend
ausgewertet werden müssen, die ja auch separat schreiben kann. Muss man
halt eine "Handvoll Zeichen" mehr schreiben.
@ Karl Heinz (kbuchegg) (Moderator)
>Nochmal, das hat mit dem if nicht das geringste zu tun.
Das weiß ich!
>Die Short Circuit Evaluation ist Eigenschaft der Operatoren && und ||.
Auch das ist klar! Aber es IMPLIZIERT die bedingte Ausführung von
Funktionen, wie man sie auch EXPLIZIT durch geschachtelte if() erreichen
kann. Jaja, mehr Schreibarbeit, aber EINDEUTLICH SICHTBAR!
>Im Urpascal musste man alle Pointer Zugriffe die man absichern wollte so>schreiben (ich verwende C Syntax, weil mein Pascal schon eingerostet>ist)> if( p )> if( *p )
Richtig, man sieht direkt, was wann passiert.
>Man konnte sich nie sicher sein, ob ein spezieller Pascal Compiler Short>Circuit machen wird oder nicht. Da solche Dinge aber in einem normalen>Programm in der Größenordnung von ein paar Zehntausend mal vorkommt, ist>das ein 'pain in the ass', wenn man das jedesmal ausschreiben muss.
Hmm, ist ein Argument. Wenn gleich ich das in der Größenordnung nicht
ganz glauben kann.
> Ganz>zu schweigen von den Schachtelungstiefen, die da ganz schnell anwachsen.
Wenn gleich ich weder Softwerker bin noch je WIRKLICH große Programme
geschrieben habe, habe ich noch NIE bewußt die short circuit evaluation
eingesetzt und meine Schachteltiefen halten sich auch im Rahmen. Jaja,
es ermöglicht kompakteren Code, aber das kann auch mal ins Auge gehen.
Karl Heinz schrieb:> Man konnte sich nie sicher sein, ob ein spezieller Pascal Compiler Short> Circuit machen wird oder nicht.
Und wenn mich mein Gedächtnis nicht täuscht, wurde dann auch in Pascal
die Short Circuit Evaluation vom De Facto Standard Setzer Turbo Pascal
in die Standard-Definition übernommen. Es hat sich einfach als
praktischer erwiesen.
@ Rolf Magnus (rmagnus)
>Wer nicht weiß, an welcher Seite er den Lötkolben anfassen muss,>verbrennt sich halt unter Umständen auch mal die Finger. ;-)
Na dann geh ich mal lieber löten. ;-)
>Was sollte an>if (a && b)>eindeutiger als bei>x = a && b;>sein? Für mich ist da kein Unterschied.
Falsches Beispiel. 2x short circuit. Es geht um Funktionen mit
Nebeneffekten! Auch die Pointerbeispiele mit den Lesezugriffen sind im
ALLGEMEINEN nebenwirkungsfrei (wenn sie nicht auf besondere
Hardwareregister wie UDR etc. zeigen HEHEHE ;-)
>Ich finde ein>schöner als ein
Ja.
>verschachtelten ifs lösen, aber das wird meines Erachtens nicht>automatisch immer lesbarer sein.
Ich meine schon. Aber wenn man lange genug auf short circuit evaluation
getrimmt ist, hat man das im Blut. Logisch.
>Ich kann ja auch umgekehrt sagen, daß man, wenn beide Seiten zwingend>ausgewertet werden müssen, die ja auch separat schreiben kann. Muss man>halt eine "Handvoll Zeichen" mehr schreiben.
Eben, aber DAS ist für den Einsteiger eine "schöne" Stolperfalle!
Falk Brunner schrieb:> Wenn gleich ich weder Softwerker bin noch je WIRKLICH große Programme> geschrieben habe,
hab ich auch noch nie.
Bei so ca. 300kLOC Projektgröße war bei mir Schluss. (ja das sind rund
300-tausend und ist kein Tippfehler). Es gibt Leute, für die ist das
immer noch Pipifax.
A. K. schrieb:> Besonders wenn dann noch ein "else" Zweig kommt. Das ist in der 3fach> "if" Version deutlich umständlicher.
LOL
Ich war mal in einem Projekt, da war es gang und gebe Dinge zb so zu
schreiben
1
rc!=func1()&&
2
rc!=func2()&&
3
rc!=func3()&&
4
rc!=func4()&&
5
rc!=func5()&&
6
rc!=func6()&&
7
rc!=func7()&&
8
rc!=func8()......
9
...
10
rc!=func23();
11
12
if(!rc)
13
printf("Fehler blabla %d\n",rc);
natürlich mit ordentlichen Funktionsnamen und Parameterlisten.
ich habe sie dafür gehasst :-)
Aber ... man gewöhnt sich an alles. Nur nicht am Dativ.
@ Karl Heinz (kbuchegg) (Moderator)
>> Wenn gleich ich weder Softwerker bin noch je WIRKLICH große Programme>> geschrieben habe,>hab ich auch noch nie.
Understatement ;-)
>Bei so ca. 300kLOC Projektgröße war bei mir Schluss. (ja das sind rund>300-tausend und ist kein Tippfehler). Es gibt Leute, für die ist das>immer noch Pipifax.
Keine Ahnung wieviel es bei mir sind, ich schätze mal unter 30k.
Mein größtes Assemblerprojekt waren mal am Ende ~7kB Binärfile, 91kB
Quelltext in einer Datei, ~8800 Zeilen ;-)
Mein aktuelles C Projekt hat gerade mal ~100kB eigenen C Quelltext (plus
externes Zeug) mit in Summe ~3500 Zeilen. Ich geh mal in die Ecke und
schäm mich.
Aber Gott sei Dank werden Softwerker nicht nach Codezeilen bezahlt ;-)
Falk Brunner schrieb:> @ Karl Heinz (kbuchegg) (Moderator)>>>> Wenn gleich ich weder Softwerker bin noch je WIRKLICH große Programme>>> geschrieben habe,>>>hab ich auch noch nie.>> Understatement ;-)
Nein nicht wirklich.
Ist so irgendwo mittlere Größe.
Es gibt viele Projekte die um einiges größer sind.
> externes Zeug) mit in Summe ~3500 Zeilen. Ich geh mal in die Ecke und> schäm mich.
Das sollst du nicht. Das war nicht der Zweck der Übung.
Worauf ich hinaus will ist, dass sich viele Dinge erst zeigen, wenns in
die Masse geht.
Karl Heinz schrieb:> Worauf ich hinaus will ist, dass sich viele Dinge erst zeigen, wenns in> die Masse geht.
Das ist zb bei C versus C++ auch nicht anders.
Klar: bei den Übungsbeispielen greift sich jeder an den Kopf, wenn er
das erste mal sieht, welcher Tippaufwand in Klassen getrieben wird.
Die Vorteile und Möglichkeiten von C++ kommen erst bei größeren
Projekten zum tragen. Dort wirds dann aber massiv.
Karl Heinz schrieb:> Ich war mal in einem Projekt, da war es gang und gebe Dinge zb so zu> schreiben>> rc != func1() &&> rc != func2() &&> ...
Ich kenne das in einer etwas abweichenden Form:
1
init1()&&
2
init2()&&
3
init3()&&
4
init4()&&
5
init5()&&
6
init6()&&
7
tuwas()||
8
printf("Fehler\n");
Wenn irgendwo in der &&-Sequenz ein Fehler auftritt (Rückgabewert =
false), wird sie abgebrochen und stattdessen der zweite Operand des
||-Ausdrucks ausgeführt, in diesem Fall die Ausgabe einer Fehlermeldung.
Ohne Short-Circuit würde man das bspw. als verschachtelte If-Anweisung
mit einer Hilfsvariablen schreiben:
1
boolok=false;
2
3
if(init1())
4
{
5
if(init2())
6
{
7
if(init3())
8
{
9
if(init4())
10
{
11
if(init5())
12
{
13
if(init6())
14
ok=tuwas();
15
}
16
}
17
}
18
}
19
}
20
if(!ok)
21
printf("Fehler\n");
Die erste Variante trifft man trotz ihrer Eleganz zwar selten in
C-Programmen, dafür aber umso häufiger in Unix-Shell-Skripten an.
Karl Heinz schrieb:> Und wenn mich mein Gedächtnis nicht täuscht, wurde dann auch in Pascal> die Short Circuit Evaluation vom De Facto Standard Setzer Turbo Pascal> in die Standard-Definition übernommen. Es hat sich einfach als> praktischer erwiesen.
So viel ich weiß, konnte man in Turbo-Pascal und dessen Nachfolgern
Delphi und Free Pascal per Compiler-Option zwischen beiden Varianten
auswählen, wobei aber Short-Circuit (abweichend vom Standard-Pascal nach
ISO/IEC 7185) der Default war.
Es gibt auch noch das Extended Pascal nach ISO/IEC 10206, das neben den
Oparatoren and und or (vollständige Auswertung) zusätzlich noch
and_then und or_else (Kurzschlussauswertung) hat, so dass man je
nach Bedarf in einem Programm mal die eine und mal die andere
Alternative verwenden kann.
Rolf Magnus schrieb:> Karl Heinz schrieb:>> Ich hab ja immer gedacht, dass Leute die ihre Sprache beherrschen und>> Erfahrung haben den größten Qualitätsboost bringen, aber scheinbar gibt>> es da auch andere Ansichten.>> Für die ist MISRA ja nicht gedacht, sondern für die Manager, die ja> auch irgendwie das Gefühl haben müssen, irgendwas für die Codequalität> getan zu haben. Dieses Gefühl können sie bekommen, indem sie> MISRA-C verordnen.
Volltreffer in Schwarze, 100% ACK!
> Tatsächlich ist das aber natürlich ein Papiertiger. Wer schlechten Code> schreibt, wird durch MISA nicht auf einmal zum Programmiergott.> Und wer sich mit C wirklich auskennt, kriegt das auch ohne MIRSA hin.
Vor allem weil der tolle MISRA Code dann so aussieht:
1
/* Violation of MISRA Rule x.y.z (Inline Assembly) */
2
inline-asm-hack-no-1;
3
4
/* Violation of MISRA Rule x.y.z (Inline Assembly) */
5
inline-asm-hack-no-2;
6
7
...
Falk Brunner schrieb:> Der unbedarfte Betrachter, so wie ich, würde nicht erwarten, dass b()> nur in Abhängigkeit des Ergebnisses von a() ausgeführt wird. Diese> Spitzfindigkeiten machen C gefährlich und werden zu Recht kritisiert.
Das ist keine Spitzfindigkeit sondern ein Sprachelement, das mit
ähnlicher Syntax und Semantik z.B. auch in Shell-Skripten üblich ist:
Johann L. schrieb:> Vor allem weil der tolle MISRA Code dann so aussieht:
:-)
Ich hab gleich nachdem ich MISRA erwähnt habe, mal danach gegoogelt, was
sie zum Thema Pointer zu sagen haben. Und bin auf das hier gestossen
http://www.misra.org.uk/forum/viewtopic.php?f=73&t=641
Ist ganz interessant zu lesen, was da Forenteilnehmer dem Mod(?) um die
Ohren schmeissen. Ungefähr im ersten Drittel gibt es einen Post (und
folgende) vom User 'Lundin' der es exakt auf den Punkt bringt.
Die Formatierkonventionen der MISRA sind ja alle ok. Nur, die hat
sowieso jeder, der industrieprogrammiert. Die Dinge die wirklich haarig
sind, lassen sich nicht per Verordnung regeln oder indem man die
Sprachmittel kastriert. Die muss man gelernt haben und beherrschen.
Alles andere ist Unsinn.
Und genau deswegen kann ich den MISRA Bemühungen nichts abgewinnen.
Ordentliche Ausbildung ist durch nichts zu ersetzen. Und irgendwann
werden es auch die Manager gelernt haben, nachdem sie die x-te Firma mit
ihren ach so tollen Spread-shits und Powerpoint Präsentationen in den
Sand gesetzt haben.
Johann L. schrieb:> Volltreffer in Schwarze, 100% ACK!Johann L. schrieb:>> Tatsächlich ist das aber natürlich ein Papiertiger. Wer schlechten Code>> schreibt, wird durch MISA nicht auf einmal zum Programmiergott.>> Und wer sich mit C wirklich auskennt, kriegt das auch ohne MIRSA hin.
Na ja. Den Versuch, "einfaches C" zu erfinden, gab's m.E. schon. Hieß
JAVA und wurde - zumindest anfangs - damit beworben, damit könne man
bessere Programme mit weniger Fehlern schreiben.
Letztendlich - das ist meine persönliche, unsachgemäße Beurteilung - hat
man damit erreicht, daß schlechtere Programmierer noch viel schlechtere
Programme schreiben.
Markus F. schrieb:> Letztendlich - das ist meine persönliche, unsachgemäße Beurteilung - hat> man damit erreicht, daß schlechtere Programmierer noch viel schlechtere> Programme schreiben.
Aber man muss zugeben, dass ein durchschnittlicher Stacktrace von einem
gecrashten Java-Programm mit dreißig und mehr Stackframes einfach nach
mehr aussieht. ;-)
Markus F. schrieb:> Letztendlich - das ist meine persönliche, unsachgemäße Beurteilung - hat> man damit erreicht, daß schlechtere Programmierer noch viel schlechtere> Programme schreiben.
Also sollte man möglichst abschreckende Sprachen verwenden, um bei den
Programmierern vorneweg die Spreu vom Weizen zu trennen? ;-)
Karl Heinz schrieb:> Erzähl das mal der MISRA> http://de.wikipedia.org/wiki/MISRA-C>> MISRA-C ist ein C-Programmierstandard aus der Automobilindustrie, der> von der englischen MISRA (Motor Industry Software Reliability> Association) erarbeitet wurde.
Ja, die englischen Autobauer ... Sind das nicht diese lustigen Vögel,
die die Lenkräder ihrer Autos auf der Beifahrerseite montieren? ;-)
A. K. schrieb:> Also sollte man möglichst abschreckende Sprachen verwenden, um bei den> Programmierern vorneweg die Spreu vom Weizen zu trennen? ;-)
Am besten Brainfuck, C oder so wäre ja zu einfach.
Yalu X. schrieb:> Ja, die englischen Autobauer ... Sind das nicht diese lustigen Vögel,> die die Lenkräder ihrer Autos auf der Beifahrerseite montieren? ;-)
Kein Wunder, wenn es dann zu Unfällen kommt! ;-)
Yalu X. schrieb:> Ich kenne das in einer etwas abweichenden Form:> init1() &&> init2() &&> init3() &&> init4() &&> init5() &&> init6() &&> tuwas() ||> printf("Fehler\n");
Was (leider) nicht geht ist das:
1
init1()||gotoout1;
2
init2()||gotoout2;
3
init3()||gotoout3;
4
tuwas();
5
out3:cleanup3();
6
out2:cleanup2();
7
out1:cleanup1();
genausowenig wie
1
for(i=0;i<42;i++){
2
preprocess()||continue;
3
calculate();
4
}
schade, denke ich manchmal ;-)
und ja, ich habe Jehova gesagt!
Edit: je mehr ich darüber nachdenke, desto mehr komme ich zur
Überzeugung, goto sollte einen return-wert haben :-) Das erlaubte
interessante Konstrukte wie
Karl Heinz schrieb:> Spread-shits
Nett. Den Begriff kannte ich noch nicht, obwohl er im Nachhinein so
offensichtlich ist. ;-)
Markus F. schrieb:> Johann L. schrieb:>>> Tatsächlich ist das aber natürlich ein Papiertiger.
Das hat nicht Johann geschrieben, sondern ich.
> Letztendlich - das ist meine persönliche, unsachgemäße Beurteilung - hat> man damit erreicht, daß schlechtere Programmierer noch viel schlechtere> Programme schreiben.
Sehe ich auch so. Man hat den schlechteren Programmieren die Möglichkeit
gegeben, auch Programme zu schreiben. Daß das der Qualität der Programme
aber nicht nicht förderlich ist, sollte einleuchten.
A. K. schrieb:> Also sollte man möglichst abschreckende Sprachen verwenden, um bei den> Programmierern vorneweg die Spreu vom Weizen zu trennen? ;-)
Das ist etwas überspitzt formuliert, aber ein bischen Wahrheit steckt da
meiner Meinung nach tatsächlich drin.
Falk Brunner schrieb:> Wenn gleich ich das in der Größenordnung nicht ganz glauben kann.
Doch, schon, wenn man denn in Pascal überhaupt Zeiger benutzt hat.
Für dynamische Daten musste man aber, da führte kein Weg dran vorbei.
Been there, done that, auch wenn's schon Jahrzehnte her ist. Damals
hätte ich mir jedenfalls eine saubere short circuit Regelung in der
Sprache mehr als gewünscht.
Yalu X. schrieb:> Die erste Variante trifft man trotz ihrer Eleganz zwar selten in> C-Programmen, dafür aber umso häufiger in Unix-Shell-Skripten an.
Eben, auch die Unix-Shell (wie z.B. sh/ksh/bash usw.) verwenden
Short-Circuit-Evaluation. Einfach, weil es im täglichen Leben eines
Programmierers absolut praktisch und sinnvoll ist.
Wenn man es konsequent nutzt, werden Programme wesentlich lesbarer - was
auch bei Shell-Scripts (also nicht nur in C) große Vorteile hat.
@Rolf Magnus (rmagnus)
>> Also sollte man möglichst abschreckende Sprachen verwenden, um bei den>> Programmierern vorneweg die Spreu vom Weizen zu trennen? ;-)>Das ist etwas überspitzt formuliert, aber ein bischen Wahrheit steckt da>meiner Meinung nach tatsächlich drin.
Separates the boys from the men.
Frank M. schrieb:> Wenn man es konsequent nutzt, werden Programme wesentlich lesbarer
Finde ich auch.
Was ist so schlimm daran, wenn man für häufige Standardfälle bessere
Schreibweisen hat und nicht alles mühsam auf unleserliche if-else
Monster runterbrechen muß. Spätestens ab der 5. if-Kaskade verliere ich
den Überblick.
Besonders unleserlich sind if-else Monster anstelle von switch/case.
Sehr schade ist, das case-Bereiche (noch) nicht im Standard sind.
Sehr gerne nehme ich auch das ?:, das gibt kurze und gut leserliche
Ausdrücke.
Das MISRA habe ich mir auch angesehen, muß wohl wirklich von einem
absoluten Programmieranfänger verfaßt worden sein. Da ist ja fast alles
verboten, was ein Programm leserlich macht.
Peter Dannegger schrieb:> Da ist ja fast alles verboten, was ein Programm leserlich macht.
Die vorhin erwähnte Strategie, möglichst unübersichtliche Programmierung
vorzusehen, um die richtigen Programmierer zu finden, wurde also in
MISRA bereits berücksichtigt? ;-)
A. K. schrieb:> Die vorhin erwähnte Strategie, möglichst unübersichtliche Programmierung> vorzusehen
scheint wohl so.
Hab noch ein wenig geschmöckert. Natürlich hauptsächlich bei
Pointer/Array Dingen.
Wir haben jetzt 2015 und die haben immer noch kein Regelset, dass in
sich konsistent wäre. Immer wieder tauchen Fälle auf, die unausweichlich
sind, nicht umgangen werden können, völlig legal und absolut üblich sind
und bei denen man bewusst den Misra Checker abschalten muss (natürlich
mit einer Begründung im Code).
Wie es einer dort mal schrieb: am besten einfach keine Arrays verwenden.
:-)
Karl Heinz schrieb:> Immer wieder tauchen Fälle auf, die unausweichlich> sind, nicht umgangen werden können, völlig legal und absolut üblich sind> und bei denen man bewusst den Misra Checker abschalten muss (natürlich> mit einer Begründung im Code).
Wahrscheinlich wird es nicht genügen, einmal ein Header-File mit allen
erforderlichen Begründungskommentaren zu schreiben und es dann in jedem
C-File zu includen? ;-)
Aber mal ehrlich: Obwohl ich den Sinn von MISRA-C nicht ganz
nachvollziehen kann, hat es mich bei einem Projekt bei einem
Automobilezulieferer auch sich allzu sehr gestört. Es kann aber auch
sein, dass die schlimmsten Regeln in dem dort verwendeten Checker
bereits deaktiviert waren.
Gibt es denn eigentlich irgendwelche empirischen Beweise, dass MISRA-C
wirklich zu weniger Fehlern im Code führt? Oder ist das lediglich eine
Erwartungshaltung?
A. H. schrieb:> Oder ist das lediglich eine Erwartungshaltung?
Wie auch andere Heilsversprechen des Software-engineerings ...
funktioniert das nur bei entsprechender Disziplin.
Peter Dannegger schrieb:> Das muß ich mir merken.> Ich hab das bisher so gemacht:do{> if( !init1() )> break;> if( !init2() )> break;> }while(0);
Boah, da ist ja selbst goto noch schöner :-O
Rufus Τ. Firefly schrieb:> A. H. schrieb:>> Oder ist das lediglich eine Erwartungshaltung?>> Wie auch andere Heilsversprechen des Software-engineerings ...> funktioniert das nur bei entsprechender Disziplin.
Das 'Schöne' an Misra ist, dass es Konfigurationen für Lint gibt. Dann
lässt man Lint über den Code drüber und der findet Regelverletzungen.
Sowas ist natürlich Wasser auf die Mühlen der Manager. Quasi
automatisiertes Qualitätsmenagement.
Karl Heinz schrieb:> Das 'Schöne' an Misra ist, dass es Konfigurationen für Lint gibt. Dann> lässt man Lint über den Code drüber und der findet Regelverletzungen.> Sowas ist natürlich Wasser auf die Mühlen der Manager. Quasi> automatisiertes Qualitätsmenagement.
Richtig, sowas ist fürs Management ein extrem wichtiges Kriterium; ob
die Entwickler sich dann einen abbrechen müssen, spielt - wenn überhaupt
- nur eine untergeordnete Rolle.
Bei uns in der Firma (multinationaler Großkonzern) haben sich vor
einigen Jahren die Leiter aller Entwicklungsabteilungen der
verschiedenen Länder zusammengesetzt und beschlossen, dass wir unsere
Windows PC Software in Zukunft nach den Regeln von MISRA-C++ schreiben
müssen.
Einwände, wie z.B. dass MISRA dafür überhaupt nicht gedacht ist (keine
Echtzeitanforderungen, kein embedded System, keine Safety-Relevanz) und
es eigentlich auch gar nicht möglich ist (nach MISRA sind streng
genommen Eingaben über eine Tastatur, Ausgaben auf einen Bildschirm und
Zugriff auf eine Festplatte nicht erlaubt, weil nicht zeitlich
deterministisch), wurden mit genau diesem Argument abgebügelt: "Es ist
aber ein Quasi-Standard und lässt sich automatisiert testen. Ausserdem
kann man ja einzelne Regeln deaktivieren."
Nun ja, wir haben nun alle Regel, die uns irgendwie in die Quere kamen,
deaktiviert. Was das Ganze jetzt noch mit MISRA zu tun hat, steht auf
einem anderen Blatt. :-/
Bernd schrieb:> Nun ja, wir haben nun alle Regel, die uns irgendwie in die Quere kamen,> deaktiviert. Was das Ganze jetzt noch mit MISRA zu tun hat, steht auf> einem anderen Blatt. :-/
:-)
You made my day.
Hauptsache es gibt Statistiken auf Knopfdruck :-)
Solche Regelwerke sind der Versuch, durch Beobachtung von denen! die's
können und Aufschreiben der vermeintlich erkannten Gesetzmäßigkeiten,
beliebige Andere, gern auch weniger begabte, zu den selben Erfolgen zu
führen.
Nur was wenn man die eigentlichen Gründe gar nicht erkannt/verstanden
hat?
Ich weiß oft nicht, warum ich heute Sachen gleich richtig mache, die ich
vor 30 Jahren ganz anders entschieden hätte.
Und wenn ich fies drauf bin, dann führ ich die Beobachter auf die völlig
falsche Fährte ;-)
Bastler schrieb:> Solche Regelwerke sind der Versuch, durch Beobachtung von denen! die's> können und Aufschreiben der vermeintlich erkannten Gesetzmäßigkeiten,> beliebige Andere, gern auch weniger begabte, zu den selben Erfolgen zu> führen.
Feynman prägte dafür den Begriff Cargo-Kult :-)
http://de.wikipedia.org/wiki/Cargo-Kult-Wissenschaft
Es sind sicher keine reinen "Beobachter". Ich glaube, dass das im Grunde
alles sehr fähige Leute sind, nur irgendwie missgeleitet :-)
Zufällig kenne ich einen der Reviewer von MISRA C:2012 persönlich, der
arbeitet in der gleiche Firma. Der Typ ist hinsichtlich C extrem
kompetent und hat glaube ich den größten Teil der Lint-Fehlercodes und
MISRA-Regeln im Kopf. (Er schreibt SIL4-Software, da braucht man das).
Nichtsdestotrotz bin ich der Meinung, dass man die Kompetenz eines
Entwicklers am besten dadurch erhöhen kann, indem man ihn mit möglichst
vielen verschiedenen Programmierstilen konfrontiert, und nicht indem man
ihm immer wieder den gleichen "verkrüppelten" Einheitsbrei vorsetzt. Ich
frage mich manchmal, was passiert, wenn ein Programmierer, der jahrelang
nur in seinem MISRA-Elfenbeinturm entwickelt hat, mit "echtem" C-Code,
der in der freien Wildbahn entstanden ist, konfrontiert wird. Der kriegt
doch einen nervösen Schock :-)
Karl Heinz schrieb:> LOL> Erzähl das mal der MISRA
Sag doch sowas nicht!
Ich muß gestehen, dass ich Shortcut Evaluations nicht kannte, bis ich
mal eine entsprechende MISRA-Warnung bekommen habe.
Da hatte ich nämlich genau so ein Konstrukt à la
1
if((x!=0)&&bar())
gebaut und der MISRA-Checker hat korrekterweise gemotzt:
"Das könnte zu unerwarteten Nebeneffekten führen, da bar() nicht
zwangsläufig aufgerufen wird. "
Bronco schrieb:> gebaut und der MISRA-Checker hat korrekterweise gemotzt:> "Das könnte zu unerwarteten Nebeneffekten führen, da bar() nicht> zwangsläufig aufgerufen wird.
nein, eben nicht korrekterweise.
Denn der Nebeneffekt ist erwartet für jeden, der halbwegs C kann.
Eben wegen solcher kranken Begründungen hat MISRA-C nichts mit C zu tun.
Es mag durchaus sein, daß man C nicht mag.
Aber dann soll man halt BASIC nehmen oder sonstwas.
Ich mache doch auch nicht alle Werkzeuge stumpf, damit sich niemand dran
verletzen kann.
Klaus Wachtler schrieb:> Ich mache doch auch nicht alle Werkzeuge stumpf, damit sich niemand dran> verletzen kann.
Sehr schöner Vergleich! Danke!
Wer mit dem Werkzeug umgehen kann, findet scharfes Werkzeug gut.
Mit freundlichen Grüßen - Martin
Klaus Wachtler schrieb:> Ich mache doch auch nicht alle Werkzeuge stumpf, damit sich niemand dran> verletzen kann.
Aber wie willst Du als Arbeitgeber sicherstellen, dass alle Deine
Programmierer ein ausreichendes KnowHow haben?
Ich hätte auch von mir behauptet, dass ich C halbwegs gut kann, aber
Shortcut Evaluations hatte ich damals nicht auf dem Schirm.
@ Bronco (Gast)
>Aber wie willst Du als Arbeitgeber sicherstellen, dass alle Deine>Programmierer ein ausreichendes KnowHow haben?
So wie überall. Durch Zeugnisse, eigene Einstellungstest, Weiterbildung
und Workshops.
Dieses Problem trifft alle höher qualifizierten Berufsgruppen.
>Ich hätte auch von mir behauptet, dass ich C halbwegs gut kann,
Jaja, behaupten und glauben kann man das immer. Sieht man auch oft hier
im Forum, wenn Leute behaupten, eine Programmiersprache oder anderes
Gebiet "ganz gut zu beherrschen" ;-)
Falk Brunner schrieb:> Jaja, behaupten und glauben kann man das immer. Sieht man auch oft hier> im Forum, wenn Leute behaupten, eine Programmiersprache oder anderes> Gebiet "ganz gut zu beherrschen" ;-)
Sagte der Mann, der Shortcut Evaluations nicht verstanden hatte... ;^)
Aber mal im Ernst:
Meines Erachtens ist C zu mächtig und zu komplex, als dass man C-KnowHow
an Zeugnissen festmachen könnte.
Insofern finde ich MISRA durchaus sinnvoll, da es die Mächtigkeit und
damit die Komplexität einschränkt, und damit eben auch die
Fehleranfälligkeit.
(Wobei es natürlich sinnvoller wäre, gleich eine einfachere
Programmiersprache zu verwenden.)
Bronco schrieb:> Insofern finde ich MISRA durchaus sinnvoll, da es die Mächtigkeit und> damit die Komplexität einschränkt, und damit eben auch die> Fehleranfälligkeit.
Laut Wikipedia ist Komplexität hier der falsche Begriff:
http://de.wikipedia.org/wiki/Komplexit%C3%A4t
Die Schwierigkeit ist es, einen gesunden Kompromiss zwischen
Einschränkung und Verlust von Funktionalität der Sprache zu finden.
MISRA ist da meiner Meinung zu weit gegangen.
Wenn ich programmiere, schränke ich mich meistens auch selbst ein. Dies
aus dem einfachen Grund, die Sicherheit, Übersichtlichkeit und
Portabilität der Software zu erhöhen. Hardwareabhängige Hacks werden mit
den nötigen Kommentaren versehen und hinter sauberen Interfaces
versteckt. Wenn möglich sogar mit Präprozessorprüfungen, damit das Ding
gar nicht kompiliert, wenn der Code die Plattform nicht unterstützt.
be stucki schrieb:> Die Schwierigkeit ist es, einen gesunden Kompromiss zwischen> Einschränkung und Verlust von Funktionalität der Sprache zu finden.> MISRA ist da meiner Meinung zu weit gegangen.
Ich würde ja jetzt wirklich gerne motzen: MISRA braucht man ja nur,
damit man billige Horden an Indern und Vietnamesen beschäftigen kann.
Aber leider finde ich auch nach 25 Jahren Programmierpraxis hier im
Forum immer wieder Diskussionen zu Details der Sprache C, die auch mir
noch neu sind (und dass, obwohl ich einige C-Bücher gelesen habe).
Bronco schrieb:> MISRA braucht man ja nur, damit man billige Horden an Indern und> Vietnamesen beschäftigen kann.
MISRA dürfte deutlich älter sein als der gegenwärtige Hype der
Börsianer, alles dahin auslagern zu lassen.
Klaus Wachtler schrieb:>> ...und der MISRA-Checker hat korrekterweise gemotzt:>> "Das könnte zu unerwarteten Nebeneffekten führen, da bar() nicht>> zwangsläufig aufgerufen wird.> nein, eben nicht korrekterweise.> Denn der Nebeneffekt ist erwartet für jeden, der halbwegs C kann.
Das Beispiel von Bronco zeigt doch, dass man auch als erfahrener
Programmierer über Sprachkonstrukte stolpert (wir sind alle
vergesslich...)
Deshalb mal ein Aufruf: Wer hat weitere Beispiele, die von Misra (bzw.
Lint/QAC/...) entdeckt wurden und von denen er sagt: "Ach du Scheiße,
das hab ich ja total übersehen!" ?
Bronco schrieb:> Aber mal im Ernst:> Meines Erachtens ist C zu mächtig und zu komplex, als dass man C-KnowHow> an Zeugnissen festmachen könnte.
Nun, eine halbstündige Unterweisung reicht eben nicht.
Wer Code schreibt, der sicherheitskritisch ist oder von dem gar Leben
abhängt, der hat verdammt nochmal ganz genau zu wissen, was er tut. In
der Chirurgie drückt man auch nicht jedem Hinz und Kunz ein kleines
Regelwerk in die Hand und läßt ihn dann einfach operieren.
> Insofern finde ich MISRA durchaus sinnvoll, da es die Mächtigkeit und> damit die Komplexität einschränkt, und damit eben auch die> Fehleranfälligkeit.
Ein Regelwerk ersetzt kein Know-How. Mit Misra kann derjenige immer noch
nicht richtig C programmieren. Es gibt manchen Leuten ein besseres
Gefühl, aber es bleibt dennoch nur gefühlte und keine echte Sicherheit.
Um nochmal auf short circuit evaluation zurück zu kommen. In C++ gibt es
das natürlich genauso aber in C++ kann man Operatoren überladen und für
die überladenen Operatoren gibt es keine short circuit evaluation. Zwar
muss für selbst definierte Operatoren mindestens ein Operand eine Klasse
sein (kein Pointer), was die Möglichkeit sich selbst in den Fuß zu
schießen schonmal deutlich entschärft. Aber es gibt ja so tolle Sachen
wie Smart-Pointer:
1
#include<iostream>
2
#include<memory>
3
usingnamespacestd;
4
5
structFoo
6
{
7
booldoSomething()
8
{
9
cout<<"doSomething called"<<endl;
10
returntrue;
11
}
12
};
13
14
booloperator&&(constshared_ptr<Foo>&lh,boolrh)
15
{
16
returnstatic_cast<bool>(lh)&&rh;
17
}
18
19
intmain()
20
{
21
shared_ptr<Foo>f;
22
if(f&&f->doSomething())
23
cout<<"Finished"<<endl;
24
}
In diesem Beispiel wird die doSomething() Funktion auf jeden Fall
aufgerufen. Am besten lässt man das Überladen von && und || einfach
sein.
Sebastian V. O. schrieb:> Am besten lässt man das Überladen von && und || einfach sein.
Genau! Man definiert dafür den Cast-Operator nach bool. Dann verhält
sich die Sache wie gewohnt.
Rolf Magnus schrieb:> Nun, eine halbstündige Unterweisung reicht eben nicht.> Wer Code schreibt, der sicherheitskritisch ist oder von dem gar Leben> abhängt, der hat verdammt nochmal ganz genau zu wissen, was er tut. In> der Chirurgie drückt man auch nicht jedem Hinz und Kunz ein kleines> Regelwerk in die Hand und läßt ihn dann einfach operieren.
Einverstanden.
Allerdings sind MISRA und sicherheitskritisch doch zwei paar Schuhe.
Jedenfalls war in meinem automobilen Berufsleben MISRA lediglich dazu
da, die Qualität der "normalen" Software zu steigern. An die
sicherheitskritische SW wurden ganz andere Anforderungen gestellt.
Bronco schrieb:> Aber wie willst Du als Arbeitgeber sicherstellen, dass alle Deine> Programmierer ein ausreichendes KnowHow haben?
Jedenfalls nicht dadurch, indem man die Programmierer durch
Besser-1000-dämliche-Einschränkungen-anstatt-fundierte-Ausbildung-Regeln
gängelt.
Durch Einschränkung der Möglichkeiten entsteht kein neues KnowHow.
Ein erster Schritt wäre, dass die Arbeitgeber Programmiere programmieren
lassen, anstatt diesen Job irgendjemand aufs Auge zu drücken, der darin
nicht kapitelfest ist und zwangsläufig damit überfordert wird.
Aber irgendein Andere-verwenden-ja-auch-das-tolle-BlaBla anzuknipsen ist
eben billiger als den Angestellten eine adäquate Aus- oder
Weiterbildung zukommen zu lassen.