Warnung bei ++index % maxwert, nicht aber bei (index +1) % maxwert

Hi

Bin soeben über einen Sketch von agmue gestolpert, wo Er einen Index hochzählt und gleichzeitig auf einen Maximalwert begrenzt. Er nutzt dafür das Konstrukt:

index = (index + 1) % anzWerte;

Selber nutze ich Ähnliches - meiner Meinung genau das Gleiche, wirft aber eine Warnung

index = ++index % anzWerte;
C:\...\arduino_modified_sketch_787353\sketch_dec31a.ino:19:31: warning: operation on 'index' may be undefined [-Wsequence-point]
     index = ++index % anzWerte;
                               ^

Worin unterscheidet sich ++index von (index + 1) und warum ist meine Variante 'undefiniert'? Funktioniert wie gewünscht, index wird zuerst inkrementiert, dann per Modulo mit dem maximal-Wert verrechnet. Raus kommt ein um 1 erhöhter Index, Der an der hinteren Grenze (auf Null) umgebrochen wird. Unschön sind halt die Warnungen, Die ich zu jeder dieser Berechnungen bekomme - benutze an 5 Stellen dieses Konstrukt, um Daten in je einen Ringspeicher (IN/OUT) zu schreiben (3x) oder auszulesen (2x).

MfG

Edit Sollte hier keinen Einfluss haben, im aktuellen Fall geht's um einen Uno

PS: die funktionierende (und warnungsfreie) Version, danke an DerFips, sieht so aus: ++index = index % anzWerte;

Das Problem ist die Kombination aus Inkrement und Zuweisung

Siehe hier: http://c-faq.com/expr/seqpoints.html

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.

Ich glaube bei Forumulierung 2 ist der Compiler nicht ganz sicher was du willst (may be undefined).

Also ob du meinst (index + 1) % anzwerte oder (index % anzwerte) + 1;

Ulli

Nein. Das ist nicht das Problem. Die Warnung kann man hier wörtlich nehmen. Das Ergebnis ist undefiniert. Da kommt eventuell raus was du erwartest, aber es kann auch was anderes sein

Hi

Aber warum KANN Da was Anderes raus kommen, als ich erwarte?
++/-- wird doch eh vorher ausgeführt, somit kann das Modulo nicht ‘irgendwie’ vorher angewendet werden.
Eine Klammerung
(++index)%anzwert;
bringt keine Besserung, die Warnung bleibt auch bei
(index++)%anzwert;
Einzig
(index + 1)%anzwert lässt die Warnung verstummen - wobei index++ <-> index +1 entsprechen sollte.
Spätestens durch die Klammerung sollte die Reihenfolge eindeutig sein, die Warnung interessiert Das aber nicht.

MfG

Edit
‘Meine’ Version spart noch ein paar Byte: (an einer Stelle geändert)

/* (x + 1) % max
Der Sketch verwendet 8578 Bytes (26%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 753 Bytes (36%) des dynamischen Speichers, 1295 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
 */

 /* ++x % max
Der Sketch verwendet 8496 Bytes (26%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 753 Bytes (36%) des dynamischen Speichers, 1295 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
  */

++/-- wird doch eh vorher ausgeführt

Denkt man natürlich leicht, aber die die Ausführungs-Reihenfolge ist nicht garantiert. Es gibt bestimmte Punkte bei denen eine Anweisung abgeschlossen ist und man ein definiertes Ergebnis hat. Dazwischen kann der Compiler was anderes draus machen. Logische Operatoren oder ein Strichpunkt z.B. schließen eine Sequenz ab

(index + 1)%anzwert

Da greift der andere Satz der Regel den ich nicht zitiert habe:

Furthermore, the prior value shall be accessed only to determine the value to be stored.

Das ist ein Lese-Zugriff und damit erlaubt

++index = index % anzahl;

So kommt keine Warnung.

Gruß Fips

Nur weil keine Warnung kommt heißt noch lange nicht dass das Ding tut was du willst.

Macht es aber!

Gruß Fips

Hi

Wow ... Das muß ich mir Mal auf der Zunge zergehen lassen ... ++index= | index wird um 1 erhöht, bevor die Zuweisung ausgeführt wird index%anzahl | der erhöhte Index wird per Modulo mit anzahl verrechnet - ergibt 0...anzahl-1 Der berechnete Wert wird zugewiesen ... könnte klappen

MfG

PS: Das klappt - bin beeindruckt!

/* ++x=x % max; OHNE Warnung
Der Sketch verwendet 8496 Bytes (26%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 753 Bytes (36%) des dynamischen Speichers, 1295 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
 */

/* x=(x + 1) % max; OHNE Warnung
Der Sketch verwendet 8578 Bytes (26%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 753 Bytes (36%) des dynamischen Speichers, 1295 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
 */

 /* x=++x % max; MIT Warnung
Der Sketch verwendet 8496 Bytes (26%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 753 Bytes (36%) des dynamischen Speichers, 1295 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
  */

Die Version von DerFips macht, was Sie soll und braucht ebenfalls nur den Platz meiner Version - nur ohne Warnung. ... ist gekauft ...

PPS: Warum bei 'meiner' Version was Anderes heraus kommen können soll, erschließt sich mir zwar immer noch nicht - mit der Fips-Lösung (Wortspiel) kann ich aber sehr gut leben - sieht außerdem ungemein interessant aus, die Zeile, und regt zum drüber hinaus Nachdenken an.

index = (index + 1) % anzWerte;

Selber nutze ich Ähnliches - meiner Meinung genau das Gleiche, wirft aber eine Warnung

index = ++index % anzWerte;

Macht, bzw. soll, NICHT das gleich machen.

index = (index + 1) % anzWerte; Read-Operation-Operation-Store

index = ++index % anzWerte; Read-Operation-Store-Operation-Store

Der nächstgelegene Sequence Point ist das jeweilige ;

OHNE Warnung

Wie schon gesagt wurde, der Compiler sieht nicht alle Probleme. Auch sind Meldungen keine Pflicht im Standard.

Hallo,

wenn man ganz sicher gehen möchte macht man es einzeln. ;)

index++;
index = index % anzWerte;

Hi

Vom verwendeten Platz ist Das mit ++index=index%anzWerte; identisch. (und mit ++index;index=index%anzWerte;)

MfG

Eigentlich halt ich mich ja gerne aus solchen Diskussionen raus, denn sie sind meist unfruchtbar, so wie Geschmacks- und Glaubensfragen auch.

Wenn schon, dann denn schon:

index++;
index %= anzWerte;

Natürlich ist die Größe gleich, auch bei einem SequencePoint Problem. Nur eben die Anordnung/Reihenfolge der ASM Statements kann falsch sein, bzw. nicht so wie der Programmierer sich das wünscht.

Hier hat man das Konzept der Sequenzen zu akzeptieren, und entsprechend zu handeln. Alternativen gibt es nicht.

Ein Grund für dieses Sequenz Konzept ist recht klar: "compiler reordering optimizations" Je mehr Spielraum man dem Compiler einräumt, desto weitergehender kann er optimieren. Das wird hier extensiv im verborgenen genutzt. Verpflichtet den Programmierer aber zu etwas Disziplin.

Und schon habe ich wieder was gelernt :)

Sicherlich nicht nur du