konvertiere int zu kurz in C

8

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.

    
user1128265 16.08.2013, 14:54
quelle

5 Antworten

4

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.

    
Magn3s1um 16.08.2013, 14:56
quelle
18

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. :

%Vor%

Allerdings ist weder die 2-Komplement-Repräsentation noch dieses Verhalten im Allgemeinen Teil des C ++ - Standards, daher ist dieses Verhalten implementierungsdefiniert.

    
dasblinkenlight 16.08.2013 14:57
quelle
9

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:

%Vor%     
Keith Thompson 16.08.2013 15:34
quelle
6

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.

    
Shafik Yaghmour 16.08.2013 15:10
quelle
3

Sie können dies tun:

%Vor%

check-sum ist 0x1234 .

Hier ist ein anderer Weg:

%Vor%

Ausgabe ist 1234 .

    
edW 26.02.2014 19:36
quelle

Tags und Links