简体   繁体   English

直接将浮点变量分配为十六进制整数与通过指针转换分配之间的区别

[英]Difference between directly assigning a float variable a hexadecimal integer and assigning through pointer conversion

I was investigating the structure of floating-point numbers, and I've found that most of compilers use IEEE 754 standard to store floating point numbers. 我正在研究浮点数的结构,发现大多数编译器使用IEEE 754标准来存储浮点数。 And when I tried to do: 当我尝试做的时候:

float a=0x3f520000; //have to be equal to 0.8203125 in IEEE 754
printf("value of 'a' is: %X [%x] %f\n",(int)a,(int)a, a);

it produces the result: 它产生结果:

value of 'a' is: 3F520000 [3f520000] 1062338560.000000

but if I try: 但是如果我尝试:

int b=0x3f520000;
float* c = (float*)&b;
printf("value of 'c' is: %X [%x] %f\r\n", *(int*)c, *(int*)c, c[0]);

it gives: 它给:

value of 'c' is: 3F520000 [3f520000] 0.820313

The second try gave me the right answer. 第二次尝试给了我正确的答案。 What is it wrong with the first try? 第一次尝试有什么问题? And why does the result differ from that when I cast int to float via pointer? 为什么结果与我通过指针将int转换为float时的结果不同?

[Note: This answer assumes C, not C++, which have different rules] [注意:此答案假设使用C,而不是C ++,它们具有不同的规则]

With

float a=0x3f520000;

you take the integer value 1062338560 and the compiler will convert it to 1062338560.0f . 您采用数值1062338560 ,编译器会将其转换为1062338560.0f

If you want hexadecimal floating point constant you must use exponent-format using the letter p . 如果需要十六进制浮点常量 ,则必须使用指数格式(使用字母p As in 0x1.a40010c6f7a0bp-1 (which is the hexadecimal notation for 0.820313 ). 就像0x1.a40010c6f7a0bp-1 (这是0.820313的十六进制表示法)一样。

What happens with 会发生什么

int b=0x3f520000;
float* c = (float*)&b;

is that you break strict aliasing and tell the compiler that c is pointing to a floating-point value (the strict aliasing break is because b isn't a floating point value). 是您破坏了严格的别名,并告诉编译器c指向浮点值(严格的别名中断是因为b 不是浮点值)。 The compiler will then reinterpret the bits in *c as a float value. 然后,编译器会将*c的位重新解释float值。

The difference is that the first converts the value ( 0x3f520000 is the integer 1062338560), and is equivalent to this: 区别在于,第一个转换值( 0x3f520000是整数1062338560),并等效于此:

float a = 1062338560;
printf("value of 'a' is: %X [%x] %f\n",(int)a,(int)a, a);

The second reinterprets the representation of the int - 111111010100100000000000000000 - as being the representation of a float instead. 第二种将int的表示形式111111010100100000000000000000重新解释为float的表示形式。
(It's also undefined, so you shouldn't expect it to do anything in particular.) (它也是未定义的,因此您不应该期望它做任何特别的事情。)

0x3f520000 is an integer constant. 0x3f520000是整数常量。 When assigned to a float, the integer is converted. 当分配给浮点数时,将转换整数。

Some more proper example of how to convert in the second case: 在第二种情况下如何进行转换的一些更合适的示例:

#include <stdio.h>
#include <string.h>
#include <stdint.h>

int main() {
  uint32_t fi = 0x3f520000;
  float f;
  memcpy(&f, &fi, sizeof(f));
  printf("%.7g\n", f);
}

it prints: 它打印:

0.8203125

so that is what you expected. 这就是您所期望的。

The approach I used is memcpy that is the safest for all compilers and best choice for modern compilers (GCC since approx. 4.6, Clang since 3.x) that interpret memcpy as "bit cast" in such case and optimize it in a efficient and safe way (at least in "hosted" mode). 我使用的方法是memcpy ,它是所有编译器最安全的方法,也是现代编译器(GCC自4.6起,Clang自3.x起)的最佳选择,这种方法在这种情况下将memcpy解释为“位强制转换”,并以高效且高效的方式对其进行了优化安全的方式(至少在“托管”模式下)。 That's still safe for older compilers, but not nessessarily efficient in the same way; 对于较旧的编译器来说,这仍然是安全的,但在同一种方式上并不一定有效。 some can prefer cast through union or ever through different pointer type. 有些人可能更喜欢通过联合或通过不同的指针类型进行强制转换。 On dangers of that ways, see here or generally search "type punning and strict aliasing". 关于这种方式的危险,请参阅此处或通常搜索“类型调整和严格别名”。

(Also, there could be some weird platforms that suffer from endianness issue that integer endianness differs from float one; ones that have byte different than 8 bits, and so on. I don't consider them here.) (此外,可能会有一些奇怪的平台遭受字节序问题,即整数字节序不同于浮点数;字节序不同于8位的字节,依此类推。在这里我不考虑它们。)

UPDATE: I was starting answering to initial version of the question. 更新:我开始回答问题的初始版本。 Yep, bit casting and value conversion will give principally different results. 是的,位转换和值转换将给出基本上不同的结果。 That's how float numbers work. 这就是浮点数的工作方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM