Zuweisung und unterschiedsprüfung in einem if

Gast #1488589
Hallo!
Ich hätte mal eine Frage bzgl. C:
Ich habe eine recht aufwendige Berechnung für einen Wert in meinem 
System, bei dessen Änderung einmalig ein bestimmter Code ausgeführt 
werden soll.
Dazu habe ich mir folgenden Code überlegt:
1
void irgendeinefunktion()
2
{
3
   static unsigned char ucLastValue;
4

5
   if(ucLastValue != (ucLastValue = aufwendigeBerechnung()))
6
   {
7
      // Verarbeitung "wert geändert"
8
   }
9
}
Das scheint leider nicht richtig zu funktionieren, die Bedingung ist 
immer '0'. Nicht das ich keine Alternative wüsste, aber warum geht das 
nicht?
LukasW schrieb:

> Das scheint leider nicht richtig zu funktionieren, die Bedingung ist
> immer '0'. Nicht das ich keine Alternative wüsste, aber warum geht das
> nicht?

Weil in C nicht definiert ist, ob bei einem Vergleich zuerst die linke 
Seite und dann die rechte Seite oder umgekehrt ausgewertet wird. Der 
Compiler darf sich das aussuchen.

Du hast darauf spekuliert, dass zuerst die linke Seite ausgewertet wird, 
der Wert irgendwo temporär zwischengespeichert wird und erst dann der 
Funktionsaufruf erfolgt, der einen neuen Wert bringt welche gleichzeitig 
in ucLastValue gespeichert wird und mit dem alten Wert aus dem 
Zwischenspeicher verglichen wird.

Du hast mit Zitronen gehandelt.

Die einzigen paar Fälle in denen du in C von einer definierten 
Auswerte-Reihenfolge ausgehen kannst, sind &&, || und , (der 
Kommaoperator, nicht zu verwechseln mit dem Komma in Argumentlisten)

Ausdrücke mit diesen Operationen werden immer von links nach rechts 
ausgewertet. Aber abgesehen von diesen Operatoren solltest du in C 
niemals von einer in irgendeiner Art und Weise definierten 
Auswertereihenfolge ausgehen. Der Compiler hat in C ziemlich viele 
Freiheiten und darf sich die Reihenfolgen aussuchen wie sie ihm in den 
Kram passen.
Wie muss man denn die Denkweise verstehen?

Also ich würde das, wenn, dann so machen:
1
static unsigned char ucNewValue;
2

3
ucNewValue = aufwendigeBerechnung();
4

5
if(ucLastValue != ucNewValue)
6
{
7
   // Verarbeitung "wert geändert"
8
}
9

10
ucLastValue = ucNewValue;

Ich weiß, dass du keine Lösungsvorschläge haben willst, aber wie kommt 
man auf so ein merkwürdiges Konstrukt?

Ich finde, Zuweisungen in if-Abfragen sollte man sich eh abgewöhnen.
Habe vor kurzer Zeit verzweifelt nach einem Bug gesucht, bis ich gesehen 
hab, dass ich statt == nur ein = geschrieben hatte.
Gast
Das ist ein typisches Beispiel, wie man Code schreibt, der aus völlig 
unverständlichen Gründen unsinnig trickreich und nicht selbsterklärend 
ist (und in diesem Fall auch noch nicht funktioniert).

Du möchtest den neuberechneten Wert mit dem aus dem vorherigen Zustand 
vergleichen,und den der Variablen ucLastValue zuweisen. Warum dann nicht 
einfach genau das hinschreiben, Zeile für Zeile, mit einer zusätzlichen 
lokalen Variablen, die den alten Wert von ucLastValue vor der 
Neuberechnung zwischenspeichert?
Denn wenn dein Ansatz funktioniert hätte, hätte der Compiler die auch 
anlegen müssen. Du sparst also mit deiner Trickserei weder Speicherplatz 
noch Rechenzeit.

Aber vielleicht ist das ja eine Übung für den obfuscated C contest.

Olvier

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.