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


von Steffen Wagner (Gast)


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:
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?

von Grrr (Gast)


Lesenswert?

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

Ja.

von Rolf Magnus (Gast)


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.

von Mark .. (mork)


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

MfG Mark

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


Lesenswert?

Mark .. schrieb:

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

Auch dann nicht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von gf (Gast)


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 :-(

von Rolf Magnus (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.