2009-10-13 3 views

ответ

18

Это проблема с приложением C-стиля. Вы должны внимательно посмотреть, что вы получаете. В вашем случае «(int)» был обычным статическим броском. Значение преобразуется в int путем усечения. В вашем случае "(int &)" был реинтерпретом. Результатом является lvalue, который ссылается на ячейку памяти b, но обрабатывается как int. На самом деле это нарушение правил строгого сглаживания. Поэтому не удивляйтесь, если ваш код больше не будет работать после включения всех оптимизаций.

Эквивалентный код с C++ стиль бросает:

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

Проверьте вашу любимую книгу C++ на эти виды забросов.

+0

Да, это отличный ответ. Но я задаю еще один вопрос. Почему ошибка «ошибка: недопустимый static_cast от типа« float »для типа« int & », произошел, когда я использовал static_cast для приведения float в int & like« float b = 1.0f; int & j = static_cast b; ». Я не нашел ограничений static_cast в моей сильной книге C++ «Язык программирования C++». – toby

+3

Это защита, которую вы получаете от использования стилей в стиле C++. Если компилятор принимает шансы static_cast, вы не делаете ничего плохого. Насколько я помню, единственными небезопасными вещами, которые статичный кастинг позволяет вам сделать, это беспрепятственное преобразование из Base */Base & to Derived */Derived & и void * в T *. Он в принципе может инвертировать неявные преобразования, не более - не считая преобразований констант. – sellibitze

+0

Привет, продаю, спасибо за вашу помощь! Я понял! – toby

1

Похоже, вы пытаетесь создать ссылку int на float, используя (int &) cast. Это не сработает, поскольку float представлены иначе, чем int. Это не будет работать.

Если представление float и int одинаково, это могло бы сработать.

2
float b = 1.0f; 
... 
int& j = (int&)b; 

Во второй конверсии, вы смотрите на область памяти, которая содержит б, как если бы это был объем памяти, который содержит Int. Значения с плавающей запятой хранятся в виде совершенно разных целых чисел, поэтому результаты действительно разные ...

11

В шестнадцатеричном виде 1065353216 - 0x3F800000. Если вы интерпретируете это как 32-битное число с плавающей запятой, вы получите 1.0. Если записать его в двоичной системе вы получите это:

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

или сгруппированы по-разному:

 
0 01111111 00000000000000000000000 
s eeeeeeee vvvvvvvvvvvvvvvvvvvvvvv 

Первый бит (s) является знаковым битом, следующие 8 бит (e) являются показателем , а последние 23 бита (v) являются значимыми. «Показатель двойной точности с плавающей запятой кодируется с использованием смещенного двоичного представления с нулевым смещением 127, также известным как смещение экспоненты в IEEE 754 standard». Интерпретируя это, вы видите, что знак 0 (положительный), показатель равен 0 (01111111 b = 127, «нулевое смещение»), а значение - 0. Это дает вам +0 который равен 1,0.

Во всяком случае, происходит то, что вы берете ссылку на float (b) и переинтерпретируете его как ссылку int (int&). Поэтому, когда вы читаете значение j, вы получаете бит от b. Интерпретируется как поплавок. Эти биты означают 1.0, но интерпретируются как int. Эти биты означают 1065353216.

Для чего это стоит, я никогда не использовал бросок, используя & как (int&). Я бы не ожидал увидеть это или использовать его в любом нормальном C++-коде.

+0

Эй, здесь есть опечатка, (v) повторяется дважды, фиксируйте первую (v) - (e). – legends2k

+0

Я прочитал код сборки, сгенерированный g ++. Это точно происходит в программе. – toby

2

В данном конкретном случае преобразование, о котором идет речь, не имеет смысла.Это попытка переосмыслить память, занимаемую объектом float и int Lvalue. Это явно незаконно в C/C++, что означает, что он вызывает неопределенное поведение. Неопределенное поведение - это единственное значение, которое оно имеет в этом случае.

1

Что вы собираетесь делать? То же самое:

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; 

Как исправить:

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; 
Смежные вопросы