2015-04-24 2 views
1

Посмотрите на эту простую программу:истолковать 4 байт Int как 4 байта поплавок

#include <iostream> 
using namespace std; 

int main() 
{ 
unsigned int i=0x3f800000; 
float* p=(float*)(&i); 
float f=*p; 
cout<<f; 
} 

Это то, что я ожидаю от программы:

  1. Последняя строка: мы должны видеть f на выходе ,
  2. Предыдущая: f - это значение, на которое указывает p.
  3. Предыдущая: p указывает на значение, которое находится в адресе переменной с именем i. (Т.е. к значению i)
  4. i является 0x3f800000

Так что ожидаем увидеть 0x3f800000 в выходе, но Он печатает 1 вместо этого. Зачем?

[email protected]:~$ ./a.out 
1 
[email protected]:~$ 
+0

Если вы распечатываете поплавок, вы должны ожидать увидеть поплавок, а не шестнадцатеричный. Эксперимент с поплавком f = static_cast (i) и float f = * reinterpret_cast (&i); –

+0

вчера у нас этот вопрос не был –

+0

@MattMcNabb Я действительно не знаю, как вам лучше знать, около 80 заданных вопросов в день в этом теге! :) Я уже не спрашивал об этом – Abraham

ответ

5

То, что вы сделали это reinterpret_cast указатель int на указатель на float и извлекаться значение float через преобразованного указатель.

В общем, это не определено поведение, но это так случилось на вашей машине, что int и float имеют одинаковый размер, и байты, которые представляют int значение 0x3f800000, также представляют float значение 1.

+2

, а компилятор не выполнял оптимизацию наложения на основе типа –

1

Не ожидайте ничего от этого кода. Поведение (float*)(&i); не определено, поскольку типы указателей не связаны.

float и int не может быть даже такого же размера. И вы можете работать над архитектурой, которая хранит float и int в совершенно разных местах в памяти. Возможно даже, что sizeof(float*) - это не то же самое, что и sizeof(int*). Вряд ли, но возможно.

+0

_float и int могут даже не быть одинакового размера. И вы можете работать над архитектурой, которая хранит float и int в совершенно разных местах в памяти, но адреса памяти имеют одинаковый размер, не так ли? (например, 32-битный или 64-разрядный) – Abraham

+0

@Abraham: на самом деле стандарт не требует: sizeof (int *) == sizeof (float *) ', но если есть какие-либо реализации C++, где они не равны, тогда они настолько редки, что я ожидаю, что вы узнаете об этом, если бы вы использовали приведенный выше код на одном. –

1

Преобразование из int в float неверно. Вы должны сделать это так:

unsigned int i=0x3f800000; 
float f=(float)i; 
cout<<f; 
2

Так что я ожидал увидеть 0x3f800000 в выходе, но он печатает 1 вместо этого. Зачем?

Поскольку 0x3f800000 имеет битовый шаблон 00111111100000000000000000000000, что если прочитать в соответствии с IEEE 754 standard представляющего поплавком 1.0 enter image description here

+0

C++ не обязана реализовывать IEEE 754, но довольно красиво. – Bathsheba

+1

@ Батшеба, но это не то, что задают. – Federico

1

Бит-шаблон, который означает 1065353216 как целое число (3f800000 в шестнадцатеричном) происходит в вашей реализации означает 1 в качестве поплавка. Не гарантируется, что это будет иметь место во всех реализациях C++, хотя это распространено, так как это бит-шаблон, представляющий 1 как 32-битный плавающий IEEE 754.

Помните также, что ваш код нарушает строгий псевдоним и поэтому имеет неопределенное поведение независимо от битовых шаблонов.