mikrocontroller.net

Forum: Compiler & IDEs Inkrementieren vor Zuweisung?


Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe gerade ein Problem bei C:

Drei gleiche Werte inkrementieren.

Warum geht allgemein:
A = B = C;
aber nicht:
A = B = C++;
sondern:
A++;
B++;
C++;

Der Zuweisungsoperator übernimmt Zuweisungen von rechts nach links wenn 
ich mich nciht täusche. Dass das Inkrement von niederer Priorität ist 
als das = weiß ich. Nur verstehe ich halt nicht, warum nicht erst 
inkrementiert und dann zugewiesen wird.

Gruß,

Seb

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst aber mit Preinkrement arbeiten:

A = B = ++C;

hier wird bereits vor der Verwendung (Zuweisung) die Variable C 
inkrementiert, in deinem Beispiel wird C erst verwendet und dann 
inkrementiert.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian schrieb:

> als das = weiß ich. Nur verstehe ich halt nicht, warum nicht erst
> inkrementiert und dann zugewiesen wird.

Weil das genau das ist, was du geschrieben hast

Post-Inkrement:

   i++

ist ein Ausdruck, der den Wert von i liefert und als Nebeneffekt i um 1 
erhöht.

Wichtig in diesem Zusammenhang: Der Wert des Ausdrucks ist der Wert von 
i vor dem Inkrementieren.

Und diesen Wert weist du an eine Variable zu

   j = i++;

j bekommt daher den Wert von i, noch bevor das Inkrement stattgefunden 
hat.
Nun ist eine Zuweisung selber wieder ein Ausdruck, der einen Wert hat. 
Nämlich den Wert der zugewiesen wurde. Auch mit diesem Wert kann man 
wieder weiterarbeiten

   k = j = i++;

das Ergebnis der Zuweisung von i nach j (das ist der zugewiesene Wert 
selber) wird an k zugewiesen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian schrieb:

> Der Zuweisungsoperator übernimmt Zuweisungen von rechts nach links wenn
> ich mich nciht täusche.

Das ist unglücklich ausgedrückt.

Der Zuweisungsoperator ist rechts-assoziativ

Damit muss der Compiler den Ausdruck

   A = B = C

als

  A = ( B = C )

lesen und damit ergibt sich dann die Auswerte-Reihenfolge 'von rechts 
nach links'

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK.

Und um das alles zu berücksichtigen nimmt man ein Präinkrement?!

Wo wird das noch alles eingesetzt? Hab dessen verwendung nie 
verstanden...

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Präinkrement ++x ist lediglich eine andere Schreibweise der sowieso 
vorhandenen Operation (x += 1) und die logische Ergänzung von 
Postinkrement.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian schrieb:
> OK.
>
> Und um das alles zu berücksichtigen nimmt man ein Präinkrement?!

Ein Präinkrement nimmst du, wenn du beim Ausdruck

   ++i

am Wert von i nach dem Inkrement interessiert bist.

                    Post-Inkrement             Prä-Inkrement

Schreibweise             i++                      ++i
Wert des Audrucks     i vor dem Inkrement       i nach dem Inkrement


> Wo wird das noch alles eingesetzt?

Immer dann wenn man eines der beiden braucht.
Beiden gemeinsam ist, dass i auf jeden Fall inkrementiert wird. Jetzt 
hängt es nur noch davon ab, welcher Wert im kompletten Ausdruck 
interessiert: der vor oder der nach dem Inkementieren. Je nachdem nimmt 
man einen der beiden. Wenn es egal ist, weil der Wert des Ausdrucks an 
sich nicht weiter interessiert, kann man im Prinzip beides nehmen. C++ 
Jünger bevorzugen dann allerdings den Prä-Inkrement. In C ist es egal.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wo wird das noch alles eingesetzt?

Am besten garnicht.

Solche verketteten Zuweisungen sind schwer verständlich und deswegen 
schlechter Code. Besser ist es, jede Zuweisung (auch Inkrement) als 
getrennte Anweisung zu schreiben.

Autor: Gastino G. (gastino)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:
> Am besten garnicht.
>
> Solche verketteten Zuweisungen sind schwer verständlich und deswegen
> schlechter Code. Besser ist es, jede Zuweisung (auch Inkrement) als
> getrennte Anweisung zu schreiben.

Richtig. Eine Programmierweise, bei der Rätselraten angesagt ist, in 
welcher Reihenfolge was ausgeführt wird und zu welchen Ergebnissen das 
dann führt, ist Müll.
Man muss nicht jeden Blödsinn mitmachen, den die C-Syntax prinzipiell 
ermöglichen würde.

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja

Gastino G. schrieb:
> Richtig. Eine Programmierweise, bei der Rätselraten angesagt ist, in
>
> welcher Reihenfolge was ausgeführt wird und zu welchen Ergebnissen das
>
> dann führt, ist Müll.

Da geb ich euch Recht.

Es gibt hier im Forum so einige Spezis die meinen sie müssten immer und 
überall shiften, obwohl eingetlich die Multiplikation/Division gemeint 
ist. Oder Spezis die mit irgendwelchen wirren #defines Flags durch 
Bitmanipulatoren á la "|=" bzw. "&=~" setzten, anstatt =1 oder =0. Der 
Code wird dadurch unglaublich erschwert, weil ja wohl kaum jemand binär 
im Kopf rechnet. Aber naja man will ja besonders anspruchsvolle Vokabeln 
in seinem Aufsatz haben.

Für mich ist es halt wichtig Code ÜBERSICHTLICH UND VERSTÄNDLICH zu 
halten. Und das ist sicherlich ein schmaler Grat.

Deshalb müssen wir halt mal drüber sprechen, was so der aktuelle Schick 
ist.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian schrieb:

> Deshalb müssen wir halt mal drüber sprechen, was so der aktuelle Schick
> ist.


Na, ja

Wenn

    a = b = c = 0;

ein Verständnisproblem heraufbeschwört, dann sollte man doch seine 
C-Kentnisse überprüfen. Auch wenn ich euch in der Sache an sich 
(verständlich und lesbar programmieren) natürlich recht gebe.

Was für den einen schon getrickst ist, ist für den anderen sonnenklar.

Wobei:
Ich muss mich da auch ein wenig an der Nase nehmen.
  int a;
  double b, c;

  b = a = c = 5.4;

welchen Wert hat b?
(Und ich gestehe: Ich weiß es auch nicht auf Anhieb, würde aber auf 5.0 
tippen :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.