Forum: Compiler & IDEs Der C Standard und wegoptimierte Funktionen


von Michl (Gast)


Lesenswert?

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
void foo()
2
{
3
    int i;
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?

von micha (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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 "&".

von Falk B. (falk)


Lesenswert?

@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.

von Oliver S. (oliverso)


Lesenswert?

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:
1
bool bfoo = (foo() == 1);
2
bool bbar = (bar() == 2);
3
 
4
if ( bfoo  &&  bbar)
5
...

Oliver

von Peter D. (peda)


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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?
1
void foo()
2
{
3
  int i;
4
5
  i = bar(1) && bar(2);
6
7
  printf("%i", i);
8
}

von Bitflüsterer (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

Falk Brunner schrieb:
> Gibt es Compileroptionen, um das auszuschalten?

Ja.
Einfach das "||" und "&&" nicht mehr benutzen.
Sondern nur noch "|" und "&" auf logische Ausdrücke.

von Peter D. (peda)


Lesenswert?

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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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
  int i = 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.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

>
1
> void foo()
2
> {
3
>    int i;
4
>    i = bar();
5
>    i = bar();
6
>    printf("%i", i);
7
> }
8
>
> 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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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.

von C-liker (Gast)


Lesenswert?

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).

von (prx) A. K. (prx)


Lesenswert?

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.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

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. ;-)

von Oliver S. (oliverso)


Lesenswert?

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

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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
int a();
2
int b();
3
4
if (a())
5
    b();
könnte ich auch schreiben:
1
int a();
2
int b();
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.

von Markus F. (mfro)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ 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! ;-)

von Karl H. (kbuchegg)


Lesenswert?

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( p AND *p )
konnte man nicht benutzen. Dieser Fall kommt aber häufig vor!

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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!

von Karl H. (kbuchegg)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Rolf Magnus schrieb:
> Ich finde ein
1
    if (p && q && p->wert == q->wert)
2
    {
3
        // tuwas
4
    }
> schöner

Besonders wenn dann noch ein "else" Zweig kommt. Das ist in der 3fach 
"if" Version deutlich umständlicher.

von Karl H. (kbuchegg)


Lesenswert?

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.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ 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 ;-)

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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
  bool ok = 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.

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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:
1
mkdir ordner && cd ordner

von Karl H. (kbuchegg)


Lesenswert?

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.

: Bearbeitet durch User
von Markus F. (mfro)


Lesenswert?

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.

von Konrad S. (maybee)


Lesenswert?

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. ;-)

von (prx) A. K. (prx)


Lesenswert?

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? ;-)

von Yalu X. (yalu) (Moderator)


Lesenswert?

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? ;-)

von SF6 (Gast)


Lesenswert?

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.

von Konrad S. (maybee)


Lesenswert?

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! ;-)

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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() || goto out1;
2
init2() || goto out2;
3
init3() || goto out3;
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
1
a += goto b;

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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.

: Bearbeitet durch Moderator
von Falk B. (falk)


Lesenswert?

@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.

von Peter D. (peda)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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? ;-)

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Yalu X. schrieb:
> Ich kenne das in einer etwas abweichenden Form:
>   init1() &&

Das muß ich mir merken.
Ich hab das bisher so gemacht:
1
do{
2
  if( !init1() )
3
    break;
4
  if( !init2() )
5
    break;
6
}while(0);

von Karl H. (kbuchegg)


Lesenswert?

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. 
:-)

von Yalu X. (yalu) (Moderator)


Lesenswert?

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.

von A. H. (ah8)


Lesenswert?

Gibt es denn eigentlich irgendwelche empirischen Beweise, dass MISRA-C 
wirklich zu weniger Fehlern im Code führt? Oder ist das lediglich eine 
Erwartungshaltung?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

A. H. schrieb:
> Oder ist das lediglich eine Erwartungshaltung?

Wie auch andere Heilsversprechen des Software-engineerings ... 
funktioniert das nur bei entsprechender Disziplin.

von radiostar (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Bernd (Gast)


Lesenswert?

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. :-/

von Karl H. (kbuchegg)


Lesenswert?

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 :-)

von Bastler (Gast)


Lesenswert?

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 ;-)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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

von Bernd (Gast)


Lesenswert?

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 :-)

von Bronco (Gast)


Lesenswert?

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. "

von Klaus W. (mfgkw)


Lesenswert?

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.

von Martin S. (led_martin)


Lesenswert?

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

von Bronco (Gast)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

@ 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" ;-)

: Bearbeitet durch User
von Bronco (Gast)


Lesenswert?

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.)

von B. S. (bestucki)


Lesenswert?

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.

von Bronco (Gast)


Lesenswert?

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).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Micca (Gast)


Lesenswert?

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!" ?

von Rolf Magnus (Gast)


Lesenswert?

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.

von Sebastian V. (sebi_s)


Lesenswert?

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
using namespace std;
4
5
struct Foo
6
{
7
  bool doSomething()
8
  {
9
    cout << "doSomething called" << endl;
10
    return true;
11
  }
12
};
13
14
bool operator&& (const shared_ptr<Foo>& lh, bool rh)
15
{
16
  return static_cast<bool>(lh) && rh;
17
}
18
19
int main()
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.

von B. S. (bestucki)


Lesenswert?

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.

: Bearbeitet durch User
von Bronco (Gast)


Lesenswert?

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.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.