2009-04-08 9 views
7

zuweisen Wenn ich den folgenden Code in C ausführen:C Integer-Überlauf Verhalten bei größerer Breite ganzer Zahlen

#include <stdint.h> 

uint16_t a = 4000; 
uint16_t b = 8000; 

int32_t c = a - b; 

printf("%d", c); 

Es richtig druckt ‚-4000‘ als Ergebnis. Allerdings bin ich ein wenig verwirrt: Sollte es keinen arithmetischen Überlauf geben, wenn eine größere vorzeichenlose ganze Zahl von der anderen subtrahiert wird? Welche Regeln spielen hier eine Rolle? Diese Frage scheint ein bisschen noobish, also würden irgendwelche Hinweise sehr geschätzt werden.

Antwort

5

Das Problem ist eigentlich etwas kompliziert. Operanden von arithmetischen Ausdrücken werden unter Verwendung spezifischer Regeln konvertiert, die Sie in Abschnitt 3.2.1.5 von Standard (C89) sehen können. In Ihrem Fall hängt die Antwort davon ab, was der Typ uint16_t ist. Wenn es kleiner als int ist, also short int, werden die Operanden in int konvertiert und Sie erhalten -4000, aber auf einem 16-Bit-System könnte uint16_tunsigned int sein und die Konvertierung in einen signierten Typ würde nicht automatisch erfolgen.

+0

Meine Referenz bezieht sich natürlich auf den alten Standard. Siehe die Antwort von tgamblin für C99. Obwohl sie dasselbe sagen. – TrayMan

+0

3.2.1.5 ist für Double/Float/Int/etc Konvertierungen. Er sucht nach integralen (long/int/char/short/etc) Promotions, die in 3.2.1.1 dieser Version des Standards enthalten sind. Es ist in 6.3.1.1 im neueren Standard, den ich oben verlinkt habe. – tgamblin

+0

Er möchte vielleicht auch 3.2.1.2 (signed/unsigned ints) – tgamblin

1

Beide Operanden werden während der Subtraktion auf int32_t hochgestuft. Wenn das Ergebnis größer als der Maximalwert für int32_t gewesen wäre, hätten Sie einen Überlauf gesehen.

3

Die kurze Antwort ist, dass diese alle während der Subtraktion zu int befördert werden. Für die lange Antwort, siehe Abschnitt 6.3.1.1 der C standard, wo es über Integer-Promotionen in arithmetischen Ausdrücken spricht. Relevant Sprache aus dem Standard:

Wenn ein int alle Werte von die Vorlagenart darstellen kann, ist der Wert auf ein int umgewandelt; ansonsten ist es konvertiert zu einem unsigned int. Diese heißen Integer-Promotionen. Alle anderen Arten sind unverändert durch die Integer-Promotions.

Die Details sind auch drin, aber sie werden ziemlich unangenehm.

0

Es gibt tatsächlich einen Überlauf, aber C sagt es Ihnen nicht.

Der Überlauf hinterlässt einen Wert von -4000, wenn er als vorzeichenbehaftete Ganzzahl interpretiert wird. Dies funktioniert wie auf 2-Komplement-Maschinen entworfen.

Versuchen Sie, das Ergebnis als nicht signiert zu interpretieren, und Sie werden feststellen, dass (u1-u2) eine scheinbar nicht verwandte Zahl ergibt, wenn Sie u1 < u2 verwenden.

Verwandte Themen