Winavr, merkwürdiger Code

Hallo,

kann mir jemand erklären, was folgende Konstruktion macht?

Es geht insbesondere um das ?

--------------------------------------------------------------

ISR (TIMER0_COMPA_vect) { TimingDelay = (TimingDelay==0) ? 0 : TimingDelay-1; }

---------------------------------------------------------------

Gruß

Stefan

Reply to
Stefan
Loading thread data ...

Hallo Stefan,

Am 20.06.2013 10:53, schrieb Stefan: > kann mir jemand erklären, was folgende Konstruktion macht? > > Es geht insbesondere um das ?

Wenn TimingDelay gleich 0 ist, dann wird TimingDelay 0 zugewiesen. Ist es ungleich 0, wird 1 abgezogen.

formatting link

Grüße, Stefan

Reply to
Stefan Wiest

Stefan schrieb:

Wenn die Bedingung vor dem Fragezeichen wahr ist, wird der Teil vor dem Doppelpunkt geliefert, ansonsten der nach dem Doppelpunkt. Wenn TimingDelay gleich Null ist, wird TimingDelay der Wert Null zugeordnet, ansonsten der Wert "TimingDelay-1".

Na ja, ich würde dann wohl eher schreiben:

if (TimingDelay) --TimingDelay;

Reply to
Edzard Egberts

Am 20.06.2013 11:04, schrieb Edzard Egberts:

oder : if (TimingDelay) TimingDelay--;

;-)

Danke an euch beide für die Info.

Gruß

Stefan

Reply to
Stefan

Stefan schrieb:

Nö, das war schon richtig so, weil die Operatoren unterschiedlichen Aufwand haben und Dein Code noch optimiert werden muss. Ganz deutlich wird das an diesem Beispiel:

"return --TimingDelay;"

vordekrementiert, kann man einfach übersetzen als:

TimingDelay= TimingDelay -1; return TimingDelay;

"return TimingDelay--;"

nachdekrementiert, erfordert zusätzlichen Zwischenspeicher:

int Retval= TimingDelay; TimingDelay= TimingDelay -1; return Retval;

In Deinem Beispiel wird der Compiler "Retval" zwar wahrscheinlich wegoptimieren, aber ich schreibe lieber gleich genau das, was ich meine.

Reply to
Edzard Egberts

Edzard Egberts :

Würde er da nicht das "--" wegoptimieren?

TimingDelay=5;

return --TimingDelay; -> 4 return TimingDelay--; -> 5

M.

Reply to
Matthias Weingart

Matthias Weingart schrieb:

TimingDelay ist 4

und TimingDelay ist ebenfalls 4:

Im "returnfall" ist also beides notwendig, wenn das Ergebnis des Operators aber nicht weiter verarbeitet wird, kann der Compiler Retval weglassen und "TimingDelay--" durch "--TimingDelay" ersetzen.

Reply to
Edzard Egberts

Und so sprach Edzard Egberts:

Und sauber (Misra7LINT) formuliert wäre das:

if (TimingDelay==0) { TimingDelay=0; } else { TimingDelay--; }

Was der Kompiler dann draus optimiert steht auf einem anderen Blatt...

Roland

Reply to
Roland Ertelt

Roland Ertelt schrieb:

Nein, auf diesem oben. :o)

Das kann ersatzlos gestrichen werden, da sich der Wert durch die Zuweisung nicht ändert.

Da der Rückgabewert nicht gebraucht wird (der Post-Operator ist der mit dem Rückgabewert) kann direkt der Pre-Operator angewandt werden. Meine Formulierung ist also schon optimiert, bevor die der Compiler zu sehen bekommt. Außerdem verständlicher.

Dass es alle so machen, bedeutet nicht unbedingt, dass man es nicht besser machen kann.

Reply to
Edzard Egberts

Edzard Egberts schrieb:

Na ja, vorausgesetzt es ist kein Refresh, da würde der Code tatsächlich bei jedem Durchlauf einen Zugriff auf die Speicherstelle durchführen. Das würde der Compiler wohl kaum "wegoptimieren", das war zu kurz gesehen. :o(

Reply to
Edzard Egberts

Und so sprach Edzard Egberts:

Nein kann es (bei safety critical applications) nicht. Dort darf es keinen impliziten Code geben. (So muss bei switch/case ebenfalls der default: Pfad explizit existieren, auch wenn er leer ist).

Unabhängig von den Festlegungen bei safety ist es einfach schlechter Stil, impliziten Code zu schreiben. (Fast so schlecht wie der Code aus dem OP) Er liest sich schlecht und andere werden unnütz belastet, wenn sie sich einarbeiten müssen.

Und wenn die Zuweisung nur dazu da ist, beim Debug einen breakpoint reinsetzen zu können...

Roland

Reply to
Roland Ertelt

Der Compiler darf die Zuweisung nicht wegoptimieren da das ganze Programm nur sinn macht wenn TimingDelay volatile definiert ist.

Die nach den bekannten vorgaben beste Verison dürfte also folgendes sein. if(TimingDelay)TimingDelay--;

--
MFG Gernot
Reply to
Gernot Fink

Vorsicht - wenn TimingDelay keine normale Variable, sondern ein SFR ist, ist das nicht zwingend gleichbedeutend!

Hergen

Reply to
Hergen Lehmann

Kann ich mir nicht vorstellen. Bei switch-case schon, denn dort ist es sinnvoll, aber bei Konstrukten wie "if (a==0) a=0;" ist das zumindest für mich nur Unsinn. Und was ist denn genau impliziter Code? Muß man immer alle lokalen Variablen bei jedem "if" setzen? Oder gar alle globalen Variablen (von denen es ja besser nicht viele geben sollte) ?

Also wenn ich als C-Programmierer sowas lese:

if (TimingDelay==0) { TimingDelay=0; } else { TimingDelay--; }

dann muß ich länger darüber nachdenken, was der Code macht, da ich solchen redundanten Code nicht schreiben würde. Das hier:

if (TimingDelay) TimingDelay--;

ist viel einfach für mich verständlich, da es auch ein übliches C-Idiom ist.

Gute Debugger können Breakpoints mit Variablenprüfungen verbinden.

--
Frank Buss, http://www.frank-buss.de 
electronics and more: http://www.youtube.com/user/frankbuss
Reply to
Frank Buss

Edzard Egberts schrieb:

... und hätte damit ein Statement mit anderer Funktion (Rückwärtszähler läuft über die 0 hinaus, während er im Original bei 0 stehenbleibt)

Reply to
Martin Gerdes

Martin Gerdes schrieb:

(Rückwärtszähler

stehenbleibt)

Hoppla! Mist gebaut! Es ist wohl schon spät. :(

Reply to
Martin Gerdes

Gernot Fink schrieb:

SEUFZ!

if (TimingDelay) --TimingDelay;

Jetzt mal aus dem Stroutrup die Deklaration dieser Operatoren:

T& operator--(); // Präfix T operator--(int); // Postfix

Der Postfix-Operator liefert also eindeutig den schon genannten zusätzlichen Rückgabewert, während der Präfix-Operator eine Referenz auf den bearbeiteten Wert liefert, also keine zusätzliche Variable anlegen muss.

Ich verstehe nicht, was daran so schwer einzusehen ist. Das ist C++, kein BASIC, und die bessere Formulierung für oben genanntes Problem ist wirklich eindeutig.

Reply to
Edzard Egberts

Edzard Egberts :

Und was passiert, wenn TimingDelay global definiert ist?

int TimingDelay;

void foo1(void) { TimingDelay=5; return --TimingDelay; } hier erwarte ich 4

void foo2(void) { TimingDelay=5; return TimingDelay--; }

a=foo1(); hier ist a=4 und TimingDelay=4 b=foo2(); hier erwarte ich b=5 und TimingDelay=4

Der post-operator dürfte ja eigentlich - der Logik nach - erst ausgeführt werden, wenn der Returnwert übergeben wurde. Naja wie auch schon in anderen Postings deutlich geworden ist, ist das Konzept der pre- und post-Operatoren relativ unverständlich. Man ist sich nicht wirklich sicher, was der Code tut

- ausser man geht mit dem Debugger drüber. Mir geht es mit regex ähnlich - auch wenn ich schon etliche regex-Ausdrücke gebastelt hab, fällt mir es unheimlich schwer das zu verstehen. Da ist ne simple pascal-ähnliche Syntax wirklich angenehmer. Vermutlich ist sowas nur was für Leute mit Inselbegabungen ;-).

M.

Reply to
Matthias Weingart

Matthias Weingart schrieb:

Jedenfalls bis man so etwas selber geschrieben hat. Ich greife noch einmal die Operator-Deklarationen aus meinem anderen Posting auf, diesmal mit Implementierung:

T& operator--() { // Präfix *this= *this -1; return *this; }

T operator--(int) { // Postfix T Ret= *this; // Hier wird der Returnwert bestimmt *this= *this -1; // Hier der Operator ausgeführt return Ret; }

Deine Logik stimmt also, die logische Abfolge erfordert aber eine zusätzliche Variable.

Reply to
Edzard Egberts

Kann man so auch nicht verallgemeinern. Je nach Prozessor kann der Code vom Aufwand her gleich sein.

Üblich sind bei C Rückgabewerte in einem definierten Register, bei den Wintel-CPUs oft AX, EAX oder RAX.

Da geht dann problemlos so etwas:

... mov eax, [variable] dec [variable] ret

vs.

... dec [variable] mov eax, [variable] ret

Zumindest könnte das ein Compiler so optimieren.

Viele Grüße, Torsten

Reply to
Torsten Schneider

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.