Ü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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren