AVR-GCC: Optimierung?

OP #6308406
Lesenswert?

Hallo zusammen,
ich schreibe gerade an einem kleinen Ladecontroller und bin dabei auf 
eine Frage gestoßen, die ich gern im Vorfeld klären möchte (also bevor 
ich den Code laufen lasse). Es geht um folgenden Codeausschnitt:
1
while (   (_batteryVoltageCB() <= _vTerminateCharge)
2
       && (_batteryCurrentCB() < _iChargeMax)
3
       && (_pwmValue < 255)
4
      ) _setChargerPWM(++(_pwmValue));
Beabsichtigt ist, dass die Funktionen ...CB() bei jedem 
Schleifendurchlauf ausgeführt werden! Geht das so, oder muss ich da 
"vorsorglich" eingreifen, damit der Compiler nicht "denkt", dass ein 
Aufruf für die ganze while(){}-Anweisung genügt?

Danke im Voraus für konstruktive Hinweise!
  Hermann
Moderator Persönliche Seite #6308413
Lesenswert?

Hermann G. schrieb:
> Beabsichtigt ist, dass die Funktionen ...CB() bei jedem
> Schleifendurchlauf ausgeführt werden! Geht das so, oder muss ich da
> "vorsorglich" eingreifen, damit der Compiler nicht "denkt", dass ein
> Aufruf für die ganze while(){}-Anweisung genügt?

Der erste Satz ist etwas mehrdeutig.

Prinzipiell werden Funktionen erstmal für jeden Schleifendurchlauf 
aufgerufen.

Aber: es greift natürlich das "Kurzschluss-Prinzip" für logische 
Verknüpfungen. Wenn also das Ergebnis von_batteryVoltageCB() größer ist 
als _vTerminateCharge, dann wird _batteryCurrentCB() nicht mehr 
aufgerufen, denn das Ergebnis des gesamten booleschen Ausdrucks ist an 
dieser Stelle klar.

Bekommst du irgendwie extra Geld für jeden Unterstrich? ;-) Oder warum 
sonst muss bei dir alles mit so einem Zeichen beginnen? Denk dran, 
Unterstrich gefolgt von Kleinbuchstabe ist OK, gefolgt von einem zweiten 
Unterstrich oder einem Großbuchstaben gehört der Bezeichner aber zum 
"implementation namespace", also Compiler und (Standard-)Bibliothek.
#6308415
Lesenswert?

Den GCC kenne ich nicht bis ins Detail. Aber es gibt C-Compiler, die von 
rechts nach links und solche, die von links nach rechts den Ausdruck 
abarbeiten. Und dann gibt es solche, die die Abarbeitung abbrechen, 
sobald das Ergebnis (in deinem Fall "falsch") feststeht.
#6308424
Lesenswert?

Als Nachtrag: Ich bewundere Programmierer, die keine Klammer zu viel 
setzen, n+1 Funktionen in einer Zeile unterbringen können. Aber ich habe 
mit dieses Spezies nie gern zusammen gearbeitet. Ich bevorzuge defensive 
Programmierung. Der Code wird nicht langsamer, nur, weil übersichtlich 
geschrieben wurde und auch mal komplexe Ausdrücke zerlegt wurden und 
eine unnötige Klammer gesetzt wurde. Spätestens, wenn in zwei Jahren der 
Nachfolger eine Änderung machen muss, freut er sich über diesen Stil.
Moderator Persönliche Seite #6308428
Lesenswert?

Georg G. schrieb:
> Ich bevorzuge defensive Programmierung.

Die würde in diesem Falle (falls der Boolesche Ausdruck tatsächlich 
exakt so beabsichtigt ist) allerdings darin münden, dass man eine 
zusätzliche Funktion einführen muss, die die Teilbedingungen dieses 
Ausdrucks sequenziell abarbeitet. Nur so kann man ihren Rückkehrwert 
auch als Abbruchbedingung für die Schleife benutzen.
Gast #6308430
Lesenswert?

Jörg W. schrieb:
> Arduino Fanboy D. schrieb:
>> Alles Blödsinn!
>
> Vor allem alle Pauschalisierungen …
>
> Es stehen hier so viele verschiedene Dinge in den Antworten, dass es
> natürlich schon recht „interessant“ anmutet, sie alle in Bausch und
> Bogen als „Blödsinn“ abzutun.

Ja...
Habs ja schon weg gemacht.....

Zum thema:
Hier würde sich evtl eine do{}while() anbieten.
Moderator Persönliche Seite #6308436
Lesenswert?

Arduino Fanboy D. schrieb:

> Habs ja schon weg gemacht.....

Gut, hat sich mit meinem Beitrag dann überschnitten.

> Zum thema:
> Hier würde sich evtl eine do{}while() anbieten.

Falls es nicht wichtig ist, ob die Schleife ggf. (bei initial bereits 
unwahrem Steuerausdruck) gar nicht durchlaufen werden soll, könnte das 
eine Variante sein. Da kann man auch gleich eine Endlosschleife nehmen 
und mit expliziten breaks verlassen.
#6308447
Lesenswert?

Ingo Less schrieb:
> Das kommt darauf an, wie deine Variablen aufgebaut sind. Volatile ->
> geht. Nicht volatile -> sollte schief gehen wenn der Optimizer zu bissig
> is.

Es geht um Funktionen, nicht um Variablen.

Georg G. schrieb:
> Der Code wird nicht langsamer, nur, weil übersichtlich
> geschrieben wurde und auch mal komplexe Ausdrücke zerlegt wurden und
> eine unnötige Klammer gesetzt wurde. Spätestens, wenn in zwei Jahren der
> Nachfolger eine Änderung machen muss, freut er sich über diesen Stil.

Ich finde den Code so eigentlich recht übersichtlich, und er enthält 
schon jede Menge der von dir gewünschten unnötigen Klammern. Allerdings 
würde ich den Inhalt der Schleife etwas klarer von der Bedingung 
trennen.
Wie würdest du es denn schreiben, damit es übersichtlicher ist?
OP #6308470
Lesenswert?

Boh, so viele Antworten in so kurzer Zeit... Danke!

Erst einmal die einfachen Dinge:
* Die Unterstriche habe ich deshalb, weil der ganze Codeschnipsel nur 
lokale Variable innerhalb (m)einer Library benutzt.
* Über Schreibweise und Formatierung von Code lässt sich herrlich 
streiten - das soll aber hier nicht das Thema sein.

Offensichtlich habe ich meine Frage nicht ganz eindeutig formuliert, wie 
Jörg schon richtig bemerkt hat. Daher hier noch einmal zur 
Verdeutlichung:

Mir ist völlig klar, dass die Schleife abgebrochen wird, wenn eine der 
Bedingungen nicht erfüllt ist, darüber müssen wir nicht diskutieren. 
Aber wenn ALLE Bedingungen erfüllt sind, wird
1
setChargerPWM(++(_pwmValue))
 ausgeführt und anschließend wieder zum Schleifenkopf verzweigt. Jetzt 
frage ich mich, ob bei dem nächsten Schleifendurchlauf die 
*CB()-Funktion(en) wieder ausgeführt werden oder ob (evtl. noch in 
Registern des Prozessors vorhandene) "alte" Werte *aus dem vorherigen 
Schleifendurchlauf* benutzt werden. Das wäre für die Applikation nämlich 
"tödlich".

Ich hoffe, die Fragestllung ist jetzt eindeutig.
#6308487
Lesenswert?

Hermann G. schrieb:
> Aber wenn ALLE Bedingungen erfüllt sind, wird setChargerPWM(++(_pwmValue))
> ausgeführt und anschließend wieder zum Schleifenkopf verzweigt. Jetzt
> frage ich mich, ob bei dem nächsten Schleifendurchlauf die
> *CB()-Funktion(en) wieder ausgeführt werden oder ob (evtl. noch in
> Registern des Prozessors vorhandene) "alte" Werte *aus dem vorherigen
> Schleifendurchlauf* benutzt werden.

Natürlich wird die Funktion wieder aufgerufen, es sei denn, der Compiler 
kann garantieren, dass sich durch das Weglassen des Aufrufs nichts 
ändert.
Gast #6308532
Lesenswert?

> * Die Unterstriche habe ich deshalb, weil der ganze Codeschnipsel nur
> lokale Variable innerhalb (m)einer Library benutzt.

Dann mach die Variablen einfach "static".  Ein Underscore hilft nur 
anscheinend - sobald ein anderes Library den gleichen Namen nutzt, 
geht's schief.  Wenn überhaupt, dann musst du einen Library-spezifischen 
Prefix verwenden, z.B. BatLib_xxx - macht aber nur Sinn, wenn das 
Library aus mehreren C-Files besteht, die auf diese gemeinsamen Namen 
zugreifen sollen.
#6308631
Lesenswert?

Hermann G. schrieb:
> Hallo zusammen,
> ich schreibe gerade an einem kleinen Ladecontroller und bin dabei auf
> eine Frage gestoßen, die ich gern im Vorfeld klären möchte (also bevor
> ich den Code laufen lasse). Es geht um folgenden Codeausschnitt:while (
> (_batteryVoltageCB() <= _vTerminateCharge)
>        && (_batteryCurrentCB() < _iChargeMax)
>        && (_pwmValue < 255)
>       ) _setChargerPWM(++(_pwmValue));

> Beabsichtigt ist, dass die Funktionen ...CB() bei jedem
> Schleifendurchlauf ausgeführt werden!

Dann sollte man das auch explizit und leicht lesbar so hinschreiben. Die 
meisten Tricks mit der ultrakompakten Schreibweise, wie sie C zuläßt, 
gehen meist daneben.

Strukturierte Programmierung auf Mikrocontrollern

http://c2.com/cgi/wiki?ThreeStarProgrammer

> Geht das so, oder muss ich da

Nö, wurde ja schon erklärt.

> "vorsorglich" eingreifen, damit der Compiler nicht "denkt", dass ein
> Aufruf für die ganze while(){}-Anweisung genügt?
Gast #6308666
Lesenswert?

Georg G. schrieb:
> Den GCC kenne ich nicht bis ins Detail.

Warum glaubst du dann hier schreiben zu muessen. Das ist alles 
Stumpfsinn.

Stichwort: "Short-circuit evaluation".

I.e. nix rechts nach links oder vielleicht.
Re TO: die *CB Funktionen werden immer aber nur wenn noetig fuer das 
Gesamtergebnis aufgerufen.

leo
Gast #6308700
Lesenswert?

Jörg W. schrieb:
> Lieber leo, irgendwie kommst du hier 3 h zu spät. Das war doch
> alles
> schon geklärt.

Ja, verteilt. Aber so absolut falsche Aussagen kann ich tw. einfach 
nicht immer unwidersprochen lassen.

BTW "nicht standardkonform" kann man auch als "fehlerhaft", "falsch" 
usw. bezeichnen. Wenn die Code-Ausfuehrung nicht mehr stimmt, ist das 
durchaus was anderes, als die Festlegung von e.g. "seconds since xxx", 
die MS sehr oft gewechselt hat.

leo

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren