Überlauf macht Vorzeichenwechsel

Gast #1955155
Lesenswert?
• ▲
▼
Hallo,
ich hätte mal ein Problem beim C Programmieren:
1
unsigned long int a,b,c;
2

3
b = blablub 
4
c = blubbla
5

6
a = b + c; // Hier könnte ein Überlauf passieren
Ich addiere zwei signed long int. Wie kann ich verhindern, das bei 
Überlauf das Vorzeichen des Ergebnisses falsch ist?
Ich würde dann lieber das Ergebnis auf 0x7FFFFFFF bzw. 0x80000000 
begrenzt haben?
Moderator (Firma: Titel) Persönliche Seite #1955178
Lesenswert?
• ▲
▼
Bastelmaus schrieb:
> Wie kann ich verhindern, das bei Überlauf das Vorzeichen
> des Ergebnisses falsch ist?
Bei einem unsigned long kann niemals das Vorzeichen falsch sein. Es 
kann bestenfalls das Ergebniss an sich falsch sein...

> Ich würde dann lieber das Ergebnis auf 0x7FFFFFFF bzw. 0x80000000
> begrenzt haben?
Warum?

Oder willst du einfach nur erkennen, dass du einen Überlauf hattest?
#1955204
Lesenswert?
• ▲
▼
Hier gibt es ein paar Ideen dazu:

http://bytes.com/topic/c/answers/523303-how-test-overflow

(erstes Suchergebnis bei Google nach "c overflow test")

Wirklich schade, daß C da nichts besseres bietet, denn viele CPUs haben 
intern ja ein Flag, daß anzeigt, ob die vorherige Rechnenoperation 
übergelaufen ist. Mir fällt da auf Anhieb der gute alte 6502 ein:

http://www.6502.org/tutorials/vflag.html
Persönliche Seite #1955210
Lesenswert?
• ▲
▼
Lothar Miller schrieb:
> Bastelmaus schrieb:
>> Wie kann ich verhindern, das bei Überlauf das Vorzeichen
>> des Ergebnisses falsch ist?
> Bei einem unsigned long kann niemals das Vorzeichen falsch sein. Es
> kann bestenfalls das Ergebniss an sich falsch sein...

Das Ergebnis ist immer richtig wenn man beruecksichtigt dass es sich 
hier um einen Restklassenring handelt.
Gast #1955239
Lesenswert?
• ▲
▼
Bastelmaus schrieb:
> unsigned long int a,b,c;

oh Mist ich wollte natürlich schreiben :-(
1
signed long int a,b,c;
2

3
b = blablub 
4
c = blubbla
5

6
a = b + c; // Hier könnte ein Überlauf passieren
sorry tut mir ganz doll leid, ich war zu hastig.
Können wir nochmal ganz von vorne anfangen?
Moderator (Firma: Titel) Persönliche Seite #1955255
Lesenswert?
• ▲
▼
Bastelmaus schrieb:
> Können wir nochmal ganz von vorne anfangen?
Dann kannst du abfragen, ob sich bei der Addition ein unerwartetes 
Ergebnis ergibt und den Wert anschliessend begrenzen. Etwa so:
1
  signed long int a,b,c;
2

3
  b = blablub 
4
  c = blubbla
5

6
  a = b + c;
7
  if (a<0 && b>0 && c>0) a=0x7fffffff;
8
  if (a>0 && b<0 && c<0) a=0x80000000;
#1955268
Lesenswert?
• ▲
▼
Du kannst auch einen Overflow detektieren, indem du vom maximal 
möglichen signed int Wert zuerst a abziehst. Dadurch erhältst du einen 
Wert, den b nicht überschreiten darf, weil es sonst zu einem Overflow 
kommt.

Hat ein bischen was von:
   Ich hab schon 80 Euro Schulden
   Wenn ich maximal in Summe 100 Euro Schulden machen darf,
   wieviele Schulden dürfen dann noch dazu kommen, damit mein
   100€ Budget nicht überschritten wird?
   Ich würde gerne noch 40€ Schulden machen, überlaufe ich damit
   meinen Rahmen oder nicht?

Wo das hinführt, wenn man Overflows erst im Nachhinein detektiert, sieht 
man ja aktuell ...
Gast #1955499
Lesenswert?
• ▲
▼
Nix Spezialität:

0x70000000 =  1879048192
0x90000000 = -1879048192

Alles angenommen 32 Bit signed. Oder einfacher ohne Berücksichtigung 
signed/unsigned (die reine Addition braucht im 2er-Komplement darauf 
keine Rücksicht nehmen) 0x70000000 + 0x90000000 = 0x100000000. In 32 Bit 
passt das nicht mehr, die 1 fällt links raus (bzw. ins Carry-Flag) und 
die restlichen Bits sind ja alle 0.
Moderator (Firma: Titel) Persönliche Seite #1955619
Lesenswert?
• ▲
▼
Andreas B. schrieb:
> 0x70000000 =  1879048192
> 0x90000000 = -1879048192
> 0x70000000 + 0x90000000 = 0x100000000
Also gibt 1879048192 + -1879048192 = 0
Ein Übertrag ist vollkommen uninteressant, und muß nicht extra behandelt 
werden.

Kurz: wenn eine positive un eine negative Zahl addiert wird, kann (für 
das Ergebnis) kein Überlauf passieren. Und dann muß auch kein Überlauf 
behandelt werden.
Gast #1959986
Lesenswert?
• ▲
▼
Ich hätte noch eine Frage, die ganz ähnlich ist, deshalb wollte ich da 
erstmal keinen neuen Thread starten.
Ich habe:
1
signed long int a,b;
2
a = bla;
3
b = blub;
4
a += b; // wie den Überlauf/Vorzeichenwechsel hier abfangen? 
5
a -= b; // Neue Variable a_alt einführen?
Gast #1960034
Lesenswert?
• ▲
▼
Wenn der Compiler etwa einen Sprung ans Ende des Programmes plaziert 
oder einen Rücksprung ins Betriebssystem (exit, abort, return, trap, 
int, ...), dann ist das Programm für meine Verhältnisse dort zu Ende.

Oder möchtest du jetzt Haare spalten?
Gast #1960885
Lesenswert?
• ▲
▼
Karl heinz Buchegger schrieb:
> Bastelmaus schrieb:
>> Ich hätte noch eine Frage, die ganz ähnlich ist, deshalb wollte ich da
>> erstmal keinen neuen Thread starten.
>
> Und welchen der vielen Vorschläge von weiter oben hast du nicht
> verstanden?

Lieber Karl heinz Buchegger,  :-)
ich denke ich habe den Vorschlag von Lothar Miller schon verstanden,
und bin auch drauf gekommen, das man auch den Fall berücksichtigen 
sollte, das b und c = -2147483648 sind.
Dann ist das falsche Ergebnis nämlich 0  :-(
Dies kann mit der Abfrage if (a>=0 ... korrigiert werden.  :-)
1
  signed long int a,b,c;
2
  b = -2147483648;
3
  c = -2147483648;
4

5
  a = b + c;
6
  if (a<0 && b>0 && c>0) a=0x7FFFFFFF;
7
  if (a>=0 && b<0 && c<0) a=0x80000000;

Meine neue Frage bezieht sich darauf, wie man es am besten macht, wenn 
man nicht a = b + c berechnen will, sondern a += b;
Ist es dann schlau, vor der Addition eine Kopie a_alt von a zu machen?
1
  signed long int a,a_alt,b;
2
  a = bla;
3
  b = blub;
4

5
        a_alt = a; // a_alt ist eine Kopie von a
6
  a += b;
7
  if (a<0 && b>0 && a_alt>0) a=0x7FFFFFFF;
8
  if (a>=0 && b<0 && a_alt<0) a=0x80000000;
Oder gibt es da noch einen Zaubertrick?  ;-)

Antwort schreiben

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.

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.