2009-07-14 15 views
2

diesen Code Gegeben:Warum fließt dieser Überlauf nicht?

int x = 20000; 
int y = 20000; 
int z = 40000; 

// Why is it printing WTF? Isn't 40,000 > 32,767? 
if ((x + y) == z) Console.WriteLine("WTF?"); 

Und ein int zu wissen, kann -32.768-32.767 halten. Warum verursacht dies keinen Überlauf?

+1

Int in 32-Bit-Maschine ist 4 Bytes, die meiste Zeit. –

+0

Haben Sie versucht, "x + y" auszudrucken, z. Vielleicht werden beide als die gleiche negative Nummer gespeichert. – MatrixFrog

+5

Int in C# ist 32 Bit * immer *. –

Antwort

21

In C#, die int Typ der Int32 Typ zugeordnet wird, die immer 32 Bits ist, signiert.

Auch wenn Sie short verwenden, wird es immer noch nicht überlaufen, weil short + short eine int standardmäßig zurück. Wenn Sie diese int in short - (short)(x + y) - umwandeln, erhalten Sie einen übergelaufenen Wert. Sie werden jedoch keine Ausnahme bekommen. Sie können checked Verhalten verwenden, um eine Ausnahme zu erhalten:

using System; 

namespace TestOverflow 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      short x = 20000; 
      short y = 20000; 
      short z; 

      Console.WriteLine("Overflowing with default behavior..."); 
      z = (short)(x + y); 
      Console.WriteLine("Okay! Value is {0}. Press any key to overflow " + 
       "with 'checked' keyword.", z); 
      Console.ReadKey(true); 

      z = checked((short)(x + y)); 
     } 
    } 
} 

Sie können Informationen über checked (und unchecked) auf MSDN. Es läuft im Grunde auf die Leistung hinaus, weil die Überprüfung auf einen Überlauf ein wenig langsamer ist als das Ignorieren (und deshalb ist das Standardverhalten normalerweise unchecked, aber ich wette, dass in einigen Compilern/Konfigurationen eine Ausnahme auf der ersten z Zuweisung auftritt .)

+0

+1 Ich würde einfach Scorgraphics Link hier hinzufügen, um es zu einer vollständigen und großartigen Antwort zu machen. –

+0

Danke für den Tipp, ich habe einige Links zu Int32, int und kurzen Typen =) hinzugefügt – Blixt

10

http://msdn.microsoft.com/en-us/library/5kzh1b5w.aspx

Typ: int Bereich: -2147483648 bis 2147483647

+0

Downvoted, weil die Antwort nicht vollständig ist. Siehe die Antwort, die die überprüfte Arithmetik beschreibt. – jasonh

+3

Die Antwort ist in Bezug auf die ursprüngliche Frage vollständig (warum gibt es keinen Überlauf). Also meiner Meinung nach ist ein Downvote falsch. Aber machen Sie stattdessen einen Vorschlag für Ihre bevorzugte Lösung. – Scoregraphic

1

Da Ints 32-Bit sind, halten Werte bis 2 GB bis zu ±.

+0

Korrekte Antwort, außer der Verwendung von GB - Ganzzahlen haben nichts mit Bytes an sich zu tun; Dies sollte ± 2G gelesen haben. ;) – stakx

2

In C# ist ein Int 4 Bytes. Also maximiert es bei 2^31 oder 2.147.483.648. Wenn Sie eine 2-Byte-Ganzzahl wünschen, verwenden Sie einen kurzen anstelle eines int.

1

Die Größe eines int ist 4 Byte, also kann es mindestens 2^31 halten, was ungefähr 2 Milliarden ist.

1

Das Schlüsselwort int entspricht dem .NET Framework Int32 type, das Ganzzahlen im Bereich von -2.147.483.648 bis 2.147.483.647 enthalten kann.

1

in C# Int (System.Int32) ist von 32 Bits, die glücklich diesen Wert speichern können.

1

Sie gegeben das Ergebnis als drucken "WTF?" .Wie sollte es einen anderen Wert anzeigen?

Int bedeutet int32 sein Angebot -2147483648 ist bis 2147483647 Sie die Reichweite von int16 gegeben: -32768 bis 32767

Dies ist der Grund, warum es keine Fehler wirft

6

Während jeder in korrekt ist sagen, dass ein "int" -Typ auf einer 32-Bit-Maschine höchstwahrscheinlich 2^32 ist, gibt es einen eklatanten Fehler in Ihrer Methodik.

Nehmen wir an, Int war 16 Bit. Sie weisen einen Wert zu, der z überläuft, sodass z selbst übergelaufen ist. Wenn Sie x + y berechnen, überlaufen Sie auch den int-Typ, es ist sehr wahrscheinlich, dass beide Fälle auf denselben Wert überlaufen, was bedeutet, dass Sie Ihre Gleichheit trotzdem treffen würden (das ist wahrscheinlich compilerabhängig, ich bin mir nicht ganz sicher, ob x + y wird gefördert.

Der richtige Weg für Ihr Experiment wäre, dass z einen größeren Datentyp als x und y hat. Zum Beispiel (Sorry für Ebene C, bin ich von C# Person nicht viel. Ich hofft es, die Methodik dargestellt, jedoch.)

int x = INT_MAX; 
int y = INT_MAX; 
int sum = x + y; 
long long z = INT_MAX+INT_MAX; 
if(sum == z) 
printf("Why didn't sum overflow?!\n"); 

Summe und z Vergleich ist wichtig, da Vergleich x + y und z noch kommen kann in Ordnung, abhängig davon, wie der Compiler die Werbung handhabt.

+0

Großes C-Beispiel. Ich habe das tatsächlich von einem C-Typ-Blog bekommen, aber ich habe es in C# gefragt, weil ich auf SO war und es das gleiche Ergebnis gab. – Kredns

1

Zunächst ist Ihr Code im Bereich für int ... Wenn es jedoch nicht im Bereich wäre, dann würde es sich auch nicht beschweren ... coz Sie vergeben nie einen Wert zurück zu einer Variablen nach dem Ausführen von X + Y in deinem if check ...

Angenommen, Sie würden X * Y machen, dann wird es berechnet und das Ergebnis wäre ein langer Wert, dann wird der Wert aus der Variablen Z genommen und zu einem Long hochgestuft, dann würden beide verglichen ... Denken Sie an das Casting von einem unteren Grundelement zu einem höheren Grundelementwert ist implizit.

int x = 200000; //In your code it was 20000 
int y = 200000; //In your code it was 20000 
int z = 40000; 

// Why is it printing WTF? Isn't 40,000 > 32,767? 
// Note: X + Y = 200000 and not < 32,767 
// would pass compiler coz you are not assigning and values are compared as longs 
// And since it's not equals to 40,000 the WTF did not got printed 
if ((x + y) == z) Console.WriteLine("WTF?");  
// And x * y >= z is true WTF MULTIPLY got printed 
if ((x * y) >= z) Console.WriteLine("WTF MULTIPLY?"); 
// Compiler would fail since x can't hold 40,00,00,00,000 
x = x * y; 
0

Alles oben genannte ist wahr, aber es ist wichtig zu wissen, dass wenn Sie eine Zahl größer als 2^32 zuweisen, wird es nicht kompilieren!

Verwandte Themen