Ich habe:
%Vor% und ich bekomme b = -1
, während ich erwarte, dass int32
in int16
( short
) konvertiert wird. Ich erwarte einen Wert und nicht -1
.
Bitte helfen Sie mir dabei.
Ihr int A ist größer als die Größe von short. Wenn Sie A in short umwandeln, erhalten Sie eine 1 im linken Bit, was darauf hinweist, dass es sich um eine negative Zahl handelt. Da du -1 bekommst, nehme ich an, dass du 1s in allen 16 Bits bekommst, was dir -2 ^ 15 + 2 ^ 14 + 2 ^ 13 ... + 2 ^ 0 geben wird, was dir geben wird -1. Kurz gesagt (kein Wortspiel beabsichtigt), können Sie die ganze Zahl nicht in einen kurzen konvertieren, wenn es zu groß ist.
Der Wert 2147483647, oder 2 31 -1, überschreitet eine 16-Bit-Ganzzahl. Seine binäre Darstellung ist Null im MSB, gefolgt von 31 Einsen in den restlichen Bits.
Es sieht so aus, als ob in Ihrer Implementierung die letzten 16 Bits in der Umwandlung in short
enthalten sind. Wenn dies der Fall ist, werden alle auf 1
gesetzt, was zu einer Zweierkomplement Darstellung von -1
führt. :
Allerdings ist weder die 2-Komplement-Repräsentation noch dieses Verhalten im Allgemeinen Teil des C ++ - Standards, daher ist dieses Verhalten implementierungsdefiniert.
Wenn Sie einen Wert in einen signierten -Typ konvertieren, erhalten Sie ein implementierungsdefiniertes -Ergebnis, wenn der Quellwert nicht in den Zieltyp passt. Das bedeutet, dass jede konforme Compiler-Dokumentation dokumentieren muss, was das Ergebnis ist.
(Anders als beim Überlauf eines arithmetischen Operators. Beispiel:
%Vor%hat tatsächlich undefiniertes Verhalten . In jedem Fall sollten Sie jedoch darauf achten, Ihren Code so zu schreiben, dass er diese Art von Problem nicht auslöst.)
Bei vielen Implementierungen, sowohl für die Konvertierung als auch für die Arithmetik, nimmt ein Überlauf, bei dem das Ziel ein N-Bit-Typ ist, einfach die N niederwertigen Bits des korrekten Ergebnisses an.
In Ihrem Fall ist int
anscheinend 32 Bits und short
sind 16 Bits (diese Größen können bei verschiedenen Implementierungen variieren). 2147483647
ist 0x7fffffff
, die unteren 16 Bits sind 0xffff
, was (wiederum in Ihrer Implementierung) die Darstellung von -1
im Typ short
ist.
Bei der Konvertierung in vorzeichenlose Typen wird das Ergebnis streng vom Standard definiert. es nimmt die niederwertigen N Bits des Ergebnisses. Und für überlaufende Fließkomma-Konvertierung (sagen wir einen sehr großen double
-Wert in float
konvertieren), ist das Verhalten nicht definiert.
Bisher ist das für C und C ++ egal. Aber nur zur Verwirrung hinzufügen, beginnend mit dem 1999-Standard ist eine überlaufende signierte Konvertierung erlaubt, ein implementierungsdefiniertes Signal zu erzeugen. C ++ hat das nicht. Ich kenne keinen Compiler, der das tatsächlich tut.
Ich erwarte einen Wert und nicht
-1
.
-1
ist "ein Wert". Gab es einen bestimmten Wert, den Sie erwartet haben?
Übrigens:
%Vor% Die Besetzung ist nicht notwendig. Zuweisungen, Initialisierungen, Parameterübergaben und return
-Anweisungen können Werte zwischen beliebigen numerischen Typen ohne Umwandlung zuweisen. Der Wert wird implizit konvertiert:
Dies ist implementation defined
behavior, zum Beispiel gcc
Integers Implementation document
sagt:
Für die Umwandlung in einen Typ der Breite N ist der Wert reduziert modulo 2 ^ N um innerhalb des Bereichs des Typs zu liegen; Kein Signal wird ausgelöst.
Das kann sich von Compiler zu Compiler unterscheiden, ich kann keine ähnlichen Dokumente für clang
oder visual studio
ausgraben.
Aus dem C ++ - Standardentwurf, Abschnitt 4.7 Integral conversions
paragraph 3
:
Wenn der Zieltyp signiert ist, ist der Wert unverändert, wenn er im Zieltyp dargestellt werden kann ( und Bitfeldbreite); Andernfalls ist der Wert implementierungsdefiniert. .
Wenn dies unsigned
wäre, hätten Sie ein perfekt definiertes Verhalten, wie im Abschnitt 2
:
Wenn der Zieltyp nicht vorzeichenbehaftet ist, ist der resultierende Wert die am wenigsten vorzeichenlose Ganzzahl, die deckungsgleich zur Quell-Ganzzahl ist (Modulo 2n, wobei n die Anzahl der Bits ist, die zur Darstellung des Typs ohne Vorzeichen verwendet werden). [Anmerkung: In einer Zweierkomplementdarstellung ist diese Umwandlung konzeptionell und es gibt keine Änderung im Bitmuster (wenn keine Kürzung erfolgt). -Hinweis]
Die Sprache ist im C99
Draft Standardabschnitt 6.3.1.3 Signed and unsigned integers
ähnlich.