Dir ist doch jetzt schon mehrfach erklärt worden, dass der Compiler den Temporary wegoptimiert, wenn er nicht verwendet wird. Was ist daran so schwer zu verstehen? Hast du's mal durch einen Compiler gejagt und dir das Assembly angesehen?
Im übrigen hast Stroustroup bei C nichts zu melden und C kennt auch weder Templates noch Referenzen; beides sind Features von C++.
Gruß, Johannes
--
>> Wo hattest Du das Beben nochmal GENAU vorhergesagt?
> Zumindest nicht öffentlich!
Das ist zwar richtig, dann aber ein anderer Code. Ich habe ja von Anfang an gesagt, dass es wegen der Optimierung beim Compilieren wahrscheinlich egal ist, welchen Operator man nimmt. Tatsache ist eben nur, dass diese Operatoren unterschiedlich implementiert sind und der Postfix-Operator in der nicht optimierten Implementierung einen zusätzlichen Schritt erfordert.
Nein, b ist tatsächlich gleich 5 - der Rückgabewert wird vor dem Dekrementieren ermittelt. Nicht optimiert würde der Code dann noch die lokale Variable dekrementieren, bevor sie verworfen wird.
Ob "TimingDelay" lokal oder global angelegt ist, macht keinen Unterschied, da die Rückgabe als Wert stattfindet. Für die globale Variable könnte man allenfalls beim Präfix-Operator ein return by Reference machen.
Und ich verstehe nicht, was so schwer daran ist einzusehen, daß diese spezielle "Optimierung" seit gut 10 Jahren obsolet ist.
So lange der Wert nicht verwendet wird, kann *jeder* Compiler den man heute überhaupt verwenden wöllte, den temporary wegoptimieren. In den Anfangstagen von C++, als Stroustrup sein Buch geschrieben hat, mag da was dran gewesen sein. Mittlerweile nicht mehr.
Und um nochmal zum Originalkontext zurückzukommen: die Funktion ist eine ISR und hat folglich keinen Returnwert. Aus semantischer Sicht sind Prefix- und Postfix-Dekrement also gleichwertig.
Nein, das habe ich selber schon von Anfang an gesagt, musste mir also nicht erklärt werden.
Du verstehst nicht, dass ich lieber Code schreibe, der nicht noch "by magic" optimiert werden muss, sondern schon vorher genau das macht, was er tun soll.
Ja, deshalb setzen sich C-Programmierer nicht mit solchen Details auseinander, das lernt man dann beim Überladen von Operatoren für eigene Klassen.
Aber in deinem Posting vom 20.6. 15:54 schreibst du etwas anderes, bist schön in die Falle getappt ;-(. Ziemlich irreführend das alles (geht mir aber genauso).
Sehr richtig. Das macht auch nochmal deutlich, daß der Programmierer der Originalvariante sich durch die Verwendung des ?-Operators nur selber ins Knie schießt. Denn aus programmlogischer Sicht ist die Zuweisung der 0 nicht notwendig (und nein, das ist erkennbar kein SFR, wo die Zuweisung gewollte Seiteneffekte haben könnte).
Die Zuweisung ist nur deswegen notwendig, weil der ?-Operator *immer* beide Zweige enthalten muß. Und durch die volatile Deklaration der Variable kann der Compiler das noch nicht mal wegoptimieren.
Schlußfolgerung: der ?-Operator mag einen höheren Coolness-Faktor haben als ein schlichtes if(). Aber man sollte darauf aufpassen, nicht vor lauter Coolness gleich auf die Nase zu fallen.
Naja ich schreib lieber Code, der gut verständlich ist; selbst wenn er auch mal nicht optimal sein sollte. Die geringere Anzahl von Fehlern ist mir da einfach mehr wert. (Meistens wird das aber heutzutage von den guten Compilern sowieso noch optimiert). Ausnahme ist lediglich - wenn es nicht anders geht und die Speed oder Codegrösse gebraucht wird. M.
Ich sehe das nicht als "Optimierung" - mir stehen zwei ähnliche Operatoren zur Verfügung und ich wende den an, der genau das gewünschte Resultat bringt. Irgendetwas schreiben und dann hoffen, dass der Compiler es schon hinbiegt, ist einfach nicht meine Arbeitsweise.
Stimmt, aber das bedeutet, der Code der läuft, ist nicht der Code, den ich geschrieben habe. Ich denke nicht, dass das unbedingt ein Merkmal guter Software ist.
Guck' Dir das bitte noch einmal genau an. Im genannten Posting ist die globale Variable 4, weil sie im Gegensatz zur lokalen Variable nach dem Dekrement nicht verworfen wird. Du verwechselst gerade den Inhalt der Variablen mit dem Rückgabewert.
Naja, nicht optimierten Code zu bemängeln ist müßig. Oft machen die Compiler das bewusst nach Schema F, weil sich nicht optimierter Code besser debuggen lässt, da man in der Regel dann den Assemblercode besser einzelnen Sourcecodezeilen zuordnen kann.
In dem hier gezeigten Beispiel wird sogar noch viel mehr optimiert, zumindest beim gcc 4.6.3 mit Optimizerflag -O2. Der Aufruf der Funktion foo2() wird im Assemblercode schlichtweg durch die Konstante 5 ersetzt.
Bei einer lokalen Variable wird das Postdekrement ohnehin wegoptimiert, da sinnlos.
Naja, also eine deart offensichtliche Optimierung, die jeder nicht hirntote Compiler heutzutage zu Stande bringt, würde ich nicht als "Magic" bezeichnen. Wohl aber deine Heransgehensweise an das Schreiben von Code als "premature optimization", ein typisches Antipattern das oft noch zu schlechterem Code führt, als wenn man die Optimierung dem Compiler überlassen hätte.
Lesbarkeit und Wartbarkeit steht an erster Stelle; Performanz da, wo man sie braucht. Ich halte es für viel besser, zu wissen, was der Compiler tut, statt zu versuchen, klüger als der Compiler zu sein. Das funktioniert ohnehin nur selten. Ein bischen in die Jahre gekommen, aber trotzdem sehr lesenswert:
formatting link
Unsinn. Denn der Unterschied zwischen einen Pre- und Postinkrement wird eben ohnehin erst dann wirklich performancetechnisch relevant, wenn es sich nicht mehr um primitive Datentypen handelt, sondern um (möglicherweise große) Objekte. Die gibt es in C nicht, daher ist das Problem nicht existent. Jeder dahergelaufene C-Programmierer weiß, dass der Unterschied zwischen pre- und postinkrement auf primitiven Datentypen völlig vernachlässigbar ist.
Gruß, Johannes
--
>> Wo hattest Du das Beben nochmal GENAU vorhergesagt?
> Zumindest nicht öffentlich!
Ich finde es ist trotzdem der richtige Ansatz den Code (wie Edzard es vorschlug) so hinzuschreiben wie man es eigentlich meint und nicht darauf zu hoffen/vertrauen, dass der Optimizer es hinterher schon geradebiegen wird. Speziell wenn es so einfach geht wie in diesem Fall und die bessere Variante nichtmal hässlicher aussieht.
Bei Microcontrollern möchte man den Optimizer bei LowLevel-Kram auch manchmal lieber ganz abschalten. Beliebtes Beispiel beim GCC für avr ist, dass der Optimizer die Reihenfolge der Befehle bei der globalen Interrupt Steuerung in unerwünschter Weise ändert (weil er das darf und nicht versteht was er damit ggf. anrichtet):
formatting link
Das ist kein Bug und da hilft kein volatile und keine barriers, nur -O0 hilft wirklich ... und dann tut es schon weh wenn man den Sourcecode nicht "richtig" geschrieben hat.
Ich habe bisher nur sehr wenig mit gcc und avr gearbeitet, aber sollten da nicht für die kritischen Stellen mittels #pragma geschützte Bereiche oder Funktionsattribute sinnvoller sein?
Da man afaik beim gcc per Funktionsattribut die angewendeten Optimierungen für einzelne Funktionen bestimmen kann, ist es sicher sinnvoll, in dem von Michael geschilderten Fall für die betroffene Funktion nur das Umsortieren abzuschalten. -O0 für die gesamte Datei wäre mit Kanonen auf Spatzen geschossen.
Mein Ansatz wäre zusätzlich noch der, daß man damit innerhalb der Datei exakt steuern und dokumentieren kann, wie der Abschnitt behandelt werden soll. Das wird auch der Nachfolger in der Firma nicht ohne weiteres ändern, während ein Optimierungsschalter im Makefile eher mal pauschal umgestellt wird.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.