www.mikrocontroller.net

Forum: Compiler & IDEs Shift + Multiplikation bei 32 Bit Controller


Autor: Harry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

für folgendes Problem habe ich keine Antwort gefunden:

Wenn im C-Code folgende Zuweisung stattfindet:

int x,a;
[...]
x = a * 100 >> 10;

Darf dann der Compiler "kürzen", sprich x = a * 25 >> 8 daraus machen? 
Ein Überlauf ist dann zwar immer noch möglich, das Ergebnis ist aber 
dennoch "genauer" als das nicht optimierte...

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn das Programm keine undefinierten Operationen enthält, dann darf der 
Compiler nur solche Optimierungen durchführen, die am Ergebnis nichts 
ändern.

Was dabei gern übersehen wird: Wenn jedoch undefinierte Operationen 
enthalten sind, dann darf etwas anderes herauskommen. Dazu zählt 
beispielsweise die Abhängigkeit von Nebeneffekten (i = i++).

Da die vorzeichenbehaftete Multiplikation bei Überlauf undefiniert ist, 
dürfte er in diesem Beispiel dann abkürzen, wenn ein Überlauf auftritt. 
Aber nur dann.

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

Bewertung
0 lesenswert
nicht lesenswert
IMHO darf er das.

Meine Argumentation:
Bei der Multiplikation könnte ein Überlauf entstehen, da es sich
aber um int Arithmetik handelt, ist undefiniert was in so einem
Fall zu geschehen hat. Daher würde ein 'kürzen' des Ausdrucks
nichts an dieser Undefiniertheit ändern. Auch ein korrektes
Ergebnis ist schliesslich im 'undefinierten Fall' ein gültiges
Ergebnis.

Anders wäre es bei unsigned Arithmetik, bei der ja vorgeschrieben
ist, wie sich Überläufe verhalten müssen.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ähm, stimmt, kommt ja normalweise das gleiche bei raus...

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Zweifelsfall würde ich im Ass-Listing nachsehen, oder besser, die 
Operationen auf mehrere Zeilen verteilen. Heutige Compiler sind schlau 
genug, damit umzugehen. Was soll sein?
Eine komplette Funktion in eine einzige Zeile zu packen, macht 
vielleicht viel Eindruck, ist aber nicht gut wartbar.

Autor: Harry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal,

vielen Dank für die Antworten.
Eins ist mir noch nicht ganz klar: Die Multiplikation hat doch höhere 
Präzedenz. Darf der Compiler dennoch machen was er will?

Ein ähnlicher Fall tritt nun zutage bei:

int x,a;
const unsigned char b = 8;
[...]
x = (a >> 8) * b;

Hier propagiert der Compiler die Konstante 'b' und berechnet b >> 8, was 
'0' ergibt. x ist also immer '0'! Ist das auch irgendwie mit "nicht 
definiert" zu argumentieren? Erhöhe ich den Typ von 'b' auf 16 bit 
(unsigned short) und mit Wert > 2^8, dann wird x auch mal > 0...

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst du letzteres Beispiel mal in übersetzbarem Testcode formulieren? 
Nützlich wäre noch zu wissen, welcher der beiden einzig verfügbaren "32 
Bit Controller" damit gemeint sein könnte.

Autor: Harry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Controller ist ein ARM7. Den vollständigen Testcode kann ich hier im 
Forum nicht bringen. Mir ist aufgefallen, dass in [...] ziemlich viel 
(geheimer!) Code stecken muss, der den Compiler zu dieser seltsamen 
Optimierung bringt. Die Zuweisung alleine in einer Funktion funktioniert 
wie gewünscht :-( Ebenso, wenn man 'b' nur als extern deklariert (aber 
das ist ja klar, weil dann keine Propagierung mehr möglich ist).

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, aber was erwartest du dir dann von dem Forum? Kaffeesatzlesen? 
Glaskugel?

Autor: Harry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hatte gehofft, dass der Codeschnipsel ausreicht, um eine generelle 
Aussage zu treffen... (was sagt denn der C90-Standard dazu?).

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kann in diesem Schnipsel nichts erkennen, was es dem Compiler 
erlaubt, daraus x=0 zu machen. Es sei denn es ergibt sich für den 
Compiler aus dem Kontext, dass stets (a >> 8) == 0 gilt.

Wenn du vermutest, dass es ein Fehler im Compiler ist: Du kannst 
natürlich darauf hoffen, dass er im Laufe der Jahre auch ohne dein Zutun 
von allein verschwindet. Aber schneller geht es, wenn du die Entwickler 
darauf stösst. Dies ist aber nur mit reproduzierbarem Testcode möglich.

Autor: Harry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich schaue mal am Montag im Büro, ob ich den Fehler weiter einkreisen 
kann. Was das Ergebnis "=0" anbetrifft, hatte ich ja schon geschrieben:
"Erhöhe ich den Typ von 'b' auf 16 bit (unsigned short) und mit Wert > 
2^8, dann wird x auch mal > 0...".
Mit
const unsigned short b = 1024;

wird die Multiplikation durchgeführt laut asm-code (dann ist aber das 
Ergebnis möglicherweise nicht definiert wegen Überlauf).

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.