Überlauf beim Rechnen oder erst beim speichern?

Gast #1591778
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:
1
unsigned char test = 250;
2
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?
Gast
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.
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,
1
 test = (test+(unsigned char)20)/(unsigned char)9;
würde da wahrscheinlich 0 rauskommen.

MfG Mark
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.
Gast
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 :-(
Gast
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

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.