2009-10-13 15 views
6
float b = 1.0f; 
int i = (int)b; 
int& j = (int&)b; 

cout << i << endl; 
cout << j << end; 

Dann war der Ausgang des i1 und die Ausgabe von 1065353216! Es ist eine große Überraschung für mich! Also, was ist die wahre Bedeutung von (int&) Umwandlung?Was ist die Bedeutung von (int &) Umwandlung in C++ ist

Antwort

18

Dies ist das Problem mit einem C-Style-Cast. Sie müssen genau hinsehen, um zu sehen, was Sie bekommen. In Ihrem Fall war "(int)" eine normale statische Besetzung. Der Wert wird durch Abschneiden in int umgewandelt. In Ihrem Fall "(int &)" war eine Reinterpret-Besetzung. Das Ergebnis ist ein Lvalue, der sich auf den Speicherplatz von b bezieht, aber als int behandelt wird. Es ist eigentlich eine Verletzung der strengen Aliasing-Regeln. Seien Sie also nicht überrascht, wenn Ihr Code nach dem Einschalten aller Optimierungen nicht mehr funktioniert.

Equivalent Code mit C++ Casts:

float b = 1.0f; 
int i = static_cast<int>(b); 
int& j = reinterpret_cast<int&>(b); 
cout<<i<<endl; 
cout<<j<<end; 

Überprüfen Sie Ihre Lieblings-C++ Buch auf diese Art von Abgüssen.

+0

Ja, es ist eine große Antwort. Aber ich bekomme noch eine Frage. Warum ein Fehler, "Fehler: ungültiger static_cast vom Typ 'float', um 'int &'" einzugeben, passierte, wenn ich static_cast verwendete, um einen Gleitkommawert nach int & gießen "float b = 1.0f; int & j = statischer_cast b;". Ich habe die Einschränkungen von static_cast in meinem favoraite C++ - Buch "Die C++ Programmiersprache" nicht gefunden. – toby

+3

Das ist der Schutz, den Sie von C++ - Casts erhalten. Wenn der Compiler einen statischen_Cast akzeptiert, besteht die Gefahr, dass Sie nichts falsch machen. Die einzigen unsicheren Dinge, die ein Static Casting erlaubt, ist eine ungeprüfte Konvertierung von Base */Base & zu Derived */Derived & und void * zu T * soweit ich mich erinnern kann. Es kann grundsätzlich implizite Konvertierungen invertieren, nicht mehr - nicht zählen const Konvertierungen. – sellibitze

+0

Hallo, sellibitze, danke für deine Hilfe! Ich hab es geschafft! – toby

1

Scheint so, als ob Sie versuchen, einen Int-Verweis auf einen Float zu erstellen, indem Sie (int &) Cast verwenden. Das wird nicht funktionieren, da Floats anders als int dargestellt werden. Dies wird nicht funktionieren.

Wenn die Darstellung von float und int gleich ist, dann könnte es funktioniert haben.

2

In der zweiten Konvertierung betrachten Sie den Speicherbereich, der b enthält, als wäre es ein Speicherbereich, der ein int enthält. Fließkommawerte werden in einer Weise gespeichert, die als Ganzzahlen völlig verschieden ist, so dass die Ergebnisse wirklich unterschiedlich sind ...

11

In hexadezimal 1065353216 ist 0x3F800000. Wenn Sie das als eine 32-Bit-Fließkommazahl interpretieren, erhalten Sie 1.0. Wenn Sie es in binären schreiben Sie diese:

 
3 F 8 0 0 0 0 0 
0011 1111 1000 0000 0000 0000 0000 0000 

Oder anders gruppiert:

 
0 01111111 00000000000000000000000 
s eeeeeeee vvvvvvvvvvvvvvvvvvvvvvv 

Das erste Bit (s) ist das Vorzeichenbit, die nächsten 8 Bits (e) sind der Exponent und die letzten 23 Bits (v) sind die Signifikanden. "Der binäre Fließkomma-Exponent mit einfacher Genauigkeit wird unter Verwendung einer versetzten Binärdarstellung codiert, wobei der Null-Offset 127 ist; auch bekannt als Exponent-Bias in der IEEE 754 standard." Wenn Sie dies interpretieren, sehen Sie, dass das Vorzeichen 0 (positiv) ist, der Exponent 0 ist (01111111 b = 127, der "Null-Offset"), und der Signifikand ist 0. Das ergibt +0 was 1,0 ist.

Wie auch immer, Sie nehmen einen Verweis auf einen Float (b) und interpretieren ihn als int-Referenz (int&). Wenn Sie also den Wert j lesen, erhalten Sie die Bits von b. Als ein Float interpretieren diese Bits bedeuten 1,0, aber interpretiert als ein int diese Bits bedeuten 1065353216.

Für was es wert ist, habe ich nie einen Guss mit & wie (int&) verwendet. Ich würde nicht erwarten, dies zu sehen oder dies in irgendeinem normalen C++ Code zu verwenden.

+0

Hey, hier ist ein Tippfehler, (v) wird zweimal wiederholt, fixiere die erste (v) an (e). – legends2k

+0

Ich lese den Assembler-Code von g ++ generiert. Dies geschieht genau im Programm. – toby

2

In diesem speziellen Fall hat die betreffende Umwandlung keine Bedeutung.Es ist ein Versuch, den durch ein Objekt float belegten Speicher und einen int L-Wert neu zu interpretieren. Dies ist explizit in C/C++ illegal, was bedeutet, dass es undefiniertes Verhalten erzeugt. Undefiniertes Verhalten - das ist die einzige Bedeutung, die es in diesem Fall hat.

1

Was wollten Sie tun? Das Gleiche:

float b = 1.0f; 
int i = (int) b; 
int* j = (int*)b;//here we treat b as a pointer to an integer 
cout<<i<<endl; 
cout<<(*j)<<endl; 

Wie zu beheben:

float b = 1.0f; 
int i = (int) b; 
int castedB = (int)b;//static_cast<int>(b); 
int& j = castedB; 
cout<<i<<endl; 
cout<<j<<endl; 
Verwandte Themen