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
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.
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.
Georg G. schrieb:> Und dann gibt es solche, die die Abarbeitung abbrechen, sobald das> Ergebnis (in deinem Fall "falsch") feststeht.
Nur diese sind standardkonform.
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.
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.
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.
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.
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.
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?
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.
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.
> * 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.
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 Mikrocontrollernhttp://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?
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
Ingo Less schrieb:> Das kommt darauf an, wie deine Variablen aufgebaut sind. Volatile ->> geht.
Das hat absolut nichts mit volatile zu tun. Die Abfragen erfolgen
schlicht so weit, bis ein fixes Ergebnis vorliegt.
leo
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