Datum: 26.06.2008 22:15
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...
Datum: 26.06.2008 22:24
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.
Datum: 26.06.2008 22:26
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.
Datum: 26.06.2008 22:30
Ähm, stimmt, kommt ja normalweise das gleiche bei raus...
Datum: 27.06.2008 11:08
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.
Datum: 05.07.2008 10:20
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...
Datum: 05.07.2008 10:45
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.
Datum: 05.07.2008 10:55
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).
Datum: 05.07.2008 11:00
Ok, aber was erwartest du dir dann von dem Forum? Kaffeesatzlesen? Glaskugel?
Datum: 05.07.2008 11:02
Ich hatte gehofft, dass der Codeschnipsel ausreicht, um eine generelle Aussage zu treffen... (was sagt denn der C90-Standard dazu?).
Datum: 05.07.2008 11:06
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.
Datum: 05.07.2008 11:24
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 Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
- Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
- Aussagekräftigen Betreff wählen
- Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
- Groß- und Kleinschreibung verwenden
- Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
- JPEG-Dateien (.jpg) nur für Fotos und Scans verwenden
- Schaltpläne, Screenshots usw. als PNG oder GIF anhängen
Formatierung (mehr Informationen...)
- [c]C-Code[/c]
- [avrasm]AVR-Assembler-Code[/avrasm]
- [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
- [math]Formel in LaTeX-Syntax[/math]
- [[Titel]] - Link zu Artikel