www.mikrocontroller.net

Forum: Compiler & IDEs Überlauf beim Rechnen oder erst beim speichern?


Autor: Steffen Wagner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich programmiere mit WinAVR.
Ich frage mich, ob beim Rechnen mit einer Variable, die zwischendurch 
beim Rechnen über ihre Grenzen überläuft ein Fehler entsteht oder ob nur 
das Ergebnis zählt:
Bsp:
unsigned char test = 250;
test = (test+20)/9;

Das Ergebnis ist 30. Aber durch die Berechnung test+20 ist der Wert 
zwischenzeitlich 270 und das ist ja mehr als ein char "fassen" kann.
Daher meine Frage, reicht es, wenn man dafür sorge trägt, dass das 
Endergebnis im Bereich des Datentyps ist oder muss man sich auch um 
Überläufe von Zwischenergebnissen Gedanken machen?

Autor: Grrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen Wagner schrieb:
> muss man sich auch um
> Überläufe von Zwischenergebnissen Gedanken machen

Ja.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steffen Wagner schrieb:
> Ich frage mich, ob beim Rechnen mit einer Variable, die zwischendurch
> beim Rechnen über ihre Grenzen überläuft ein Fehler entsteht oder ob
> nur das Ergebnis zählt:

Wenn's der Compiler selbst rechnet, muß er das Verhalten der 
Zielmaschine emulieren und das selbe Ergebnis rausbekommen, das auch die 
Berechnung zur Laufzeit ergeben hätte.

> Das Ergebnis ist 30. Aber durch die Berechnung test+20 ist der Wert
> zwischenzeitlich 270 und das ist ja mehr als ein char "fassen" kann.

Das ist egal, da diese Berechnung sowieso in int durchgeführt wird und 
dort das Zwischenergebnis reinpasst.

> Daher meine Frage, reicht es, wenn man dafür sorge trägt, dass das
> Endergebnis im Bereich des Datentyps ist oder muss man sich auch um
> Überläufe von Zwischenergebnissen Gedanken machen?

Man muß sich die Gedanken machen. Aber im oben beschriebenen Fall gibt 
es wie gesagt keinen Überlauf.

Autor: Mark .. (mork)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Durch die Addition von 20 wird der Zwischenwert zu einem int (also 16bit 
beim AVR) konvertiert, da 20 ein int ist und der Compiler den 
berechneten Werttyp ständig auf den breitesten verwendeten Teil anpasst 
(Integer Promotion). Bei der Division duch 9 wird also mit einem int 
gerechnet. Wenn Du jeden Oparand nach unsigned char casten würdest,
 test = (test+(unsigned char)20)/(unsigned char)9;
 
würde da wahrscheinlich 0 rauskommen.

MfG Mark

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

Bewertung
0 lesenswert
nicht lesenswert
Steffen Wagner schrieb:

> Das Ergebnis ist 30. Aber durch die Berechnung test+20 ist der Wert
> zwischenzeitlich 270 und das ist ja mehr als ein char "fassen" kann.

Wobei in deinem ganz speziellen Fall sogar das richtige Ergebnis 
rauskommen wird.

Warum?
C-Regeln!

Gerechnet wird grundsätzlich niemals mit einem kleineren Datentyp als 
int.
D.h. während der Berechnung von

    test + 20

wird der Wert von test auf einen int hochgehoben und die Berechnung 
durchgeführt.
Der Ausdruck '(test + 20) / 9' hat den Datentyp int und nicht unsigned 
char. Erst bei der Zuweisung des Ergebnisses an test wird dieses 
Ergebnis wieder auf unsigned char zurechtgestutzt.

Nur dann, wenn der Compiler beweisen kann, dass es keinen Unterschied 
macht, ob er die komplette Berechnung in unsigned char oder in int 
durchführt, darf der Optimizer die Berechnung so zurechtstutzen, dass 
sich eine schnellere Bearbeitung ergibt. Es gilt die 'As if' Regel: Das 
Programm muss sich nach aussen so verhalten, als ob diese Optimierung 
nie stattgefunden hätte. Solange also das Ergebnis identisch ist zu 
jenem, welches durch striktes Anwenden der C-Regeln erhalten werden 
würde, darf der Optimizer schalten und walten wie er will.

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

Bewertung
0 lesenswert
nicht lesenswert
Mark .. schrieb:

> gerechnet. Wenn Du jeden Oparand nach unsigned char casten würdest,
>
 test = (test+(unsigned char)20)/(unsigned char)9;
>  
> würde da wahrscheinlich 0 rauskommen.

Auch dann nicht.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark .. schrieb:
> da 20 ein int ist und der Compiler den
> berechneten Werttyp ständig auf den breitesten verwendeten Teil anpasst
> (Integer Promotion).

Nur halb richtig.  Er passt ihn erst einmal mindestens auf `int' an,
erst danach dann ggf. noch größer.

Autor: gf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Gerechnet wird grundsätzlich niemals mit einem kleineren Datentyp als
> int.


Alle Berechnungen auf nem 8-Bitter werden erst mal auf 16 bit erweitert?
Das wär ja blöd :-(

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gf schrieb:
> Karl heinz Buchegger schrieb:
>> Gerechnet wird grundsätzlich niemals mit einem kleineren Datentyp als
>> int.
>
>
> Alle Berechnungen auf nem 8-Bitter werden erst mal auf 16 bit
> erweitert?
> Das wär ja blöd :-(

Das ist aber tatsächlich so. Der Compiler darf diese Größen-Erweiterung 
natürlich wegoptimeren, wenn er garantieren kann, daß das Ergebnis sich 
dadurch nicht ändert, z.B. bei den ganzen logischen Operatoren.

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.