int 到 float 的不安全转换,*(float*) (&num) 是做什么的?
In int to float unsafe conversion, what's does *(float*) (&num) do?
我正在写一个流 API,它使用了很多必须处理 BigEndian/LittleEndian 和无符号与有符号转换的东西。我有以下代码,它确实有效。但我想知道它在做什么,可以请一些 ELI5(像我 5 岁一样解释)吗?
int num = ReadInt();
return *(float*) (&num);
public int ReadInt()
{
return
(_memoryStream.ReadByte() << 0x18) |
(_memoryStream.ReadByte() << 0x10) |
(_memoryStream.ReadByte() << 0x08) |
_memoryStream.ReadByte();
}
现在我明白了 ReadInt 的作用,它只是将 LittleEndian 转换为 BigEndian。我似乎无法理解的部分是 *(float*)(&num)
.
我猜它在做某种记忆转移,但不是 100%。
一步步解释:
&
获取指向 num
. 中包含的对象的指针
(float *)
将此指针转换为浮点指针。
*
取消对this指针的引用,即获取该指针处的值。
总的来说,这 returns 字节流中最近的四个字节作为浮点数。不过,您可能会说,这可能不是最好的编码方式。
如果我敢猜的话,这是这样写的,因为 int
和 float
之间的直接转换会 preserve the value 而不是 preserve the value正在读入的字节数,这可能不是所需的行为。
&num
-- "the address of num
",这是一个指向整数的指针。
(float*)&num
- "the address of num
, converted to a pointer to float."
这是num
的内存地址,但编译器会将其内容解释为浮点数,而不是整数。
*(float*)&num
- "the address of num
, converted to a pointer to float"的内容 - 也就是说,将num
占用的内存作为浮点数读出。
因此,如果您要读取字节 0x40、0x10、0x00、0x00,
你会在内存位置得到整数 0x40100000 = 1074790400 'num'
'num' 的地址将被转换为指向浮点数的指针,并且
你会提取其中的内容。常量 0x40100000,在解释时
作为浮点数,是 2.25,这就是你要 return.
假设这是不安全的 C# 代码,ReadInt
通过将每个字节移动 24 位、16 位,将 BigEndian 有序字节流中的 4 个字节加载到 int
的 4 个字节中, 8bits, 和 0(与 C
等语言不同,.Net
中的 int
保证是 4 个字节,无论平台如何。
如您所料,这可能是 'endian-agnostic' 库的一部分,该库使用自己专有的二进制序列化格式。几乎肯定会有一个相应的 SaveInt
方法,它同样会以相应的字节顺序将 4 字节的 int 保存到流中。
别人已经解释过了,即代码:
int num = ReadInt();
return *(float*) (&num);
重新解释假定的 32 位 int
的前 4 个字节(存储在内存中),作为单精度浮点数,存储为 IEEE 754 格式浮点布局 here.使用的技术是将指向 int 地址的指针重新转换为指向 float 的指针,然后对值进行取值。
重要的是,float
也存储在 .Net 中的 4 个字节中(与我们读过的 int
大小相同):
- 1 位符号
- 8 位指数
- 23 位尾数
为什么?从 int 到 float 的直接转换:
int num = ReadInt();
return (float)num;
不会恢复原始的 'float' 序列化为 4 字节,而是保留 4 字节 int 的整数值。
既然你说这段代码来自一个库,那么 ReadInt
很可能也是其他转换中使用的实用方法 - 即其他消耗 4 个字节的类型也可以使用 ReadInt
方法可能会做类似的 post-read 'reinterpretation' 读取的字节。
这种技术显然存在危险,例如如果返回的 int
占用的字节数不足以满足更大的数据类型,例如:
int num = ReadInt();
return *(double*) (&num); // Oops.
我正在写一个流 API,它使用了很多必须处理 BigEndian/LittleEndian 和无符号与有符号转换的东西。我有以下代码,它确实有效。但我想知道它在做什么,可以请一些 ELI5(像我 5 岁一样解释)吗?
int num = ReadInt();
return *(float*) (&num);
public int ReadInt()
{
return
(_memoryStream.ReadByte() << 0x18) |
(_memoryStream.ReadByte() << 0x10) |
(_memoryStream.ReadByte() << 0x08) |
_memoryStream.ReadByte();
}
现在我明白了 ReadInt 的作用,它只是将 LittleEndian 转换为 BigEndian。我似乎无法理解的部分是 *(float*)(&num)
.
我猜它在做某种记忆转移,但不是 100%。
一步步解释:
&
获取指向num
. 中包含的对象的指针
(float *)
将此指针转换为浮点指针。*
取消对this指针的引用,即获取该指针处的值。
总的来说,这 returns 字节流中最近的四个字节作为浮点数。不过,您可能会说,这可能不是最好的编码方式。
如果我敢猜的话,这是这样写的,因为 int
和 float
之间的直接转换会 preserve the value 而不是 preserve the value正在读入的字节数,这可能不是所需的行为。
&num
-- "the address of num
",这是一个指向整数的指针。
(float*)&num
- "the address of num
, converted to a pointer to float."
这是num
的内存地址,但编译器会将其内容解释为浮点数,而不是整数。
*(float*)&num
- "the address of num
, converted to a pointer to float"的内容 - 也就是说,将num
占用的内存作为浮点数读出。
因此,如果您要读取字节 0x40、0x10、0x00、0x00, 你会在内存位置得到整数 0x40100000 = 1074790400 'num' 'num' 的地址将被转换为指向浮点数的指针,并且 你会提取其中的内容。常量 0x40100000,在解释时 作为浮点数,是 2.25,这就是你要 return.
假设这是不安全的 C# 代码,ReadInt
通过将每个字节移动 24 位、16 位,将 BigEndian 有序字节流中的 4 个字节加载到 int
的 4 个字节中, 8bits, 和 0(与 C
等语言不同,.Net
中的 int
保证是 4 个字节,无论平台如何。
如您所料,这可能是 'endian-agnostic' 库的一部分,该库使用自己专有的二进制序列化格式。几乎肯定会有一个相应的 SaveInt
方法,它同样会以相应的字节顺序将 4 字节的 int 保存到流中。
别人已经解释过了,即代码:
int num = ReadInt();
return *(float*) (&num);
重新解释假定的 32 位 int
的前 4 个字节(存储在内存中),作为单精度浮点数,存储为 IEEE 754 格式浮点布局 here.使用的技术是将指向 int 地址的指针重新转换为指向 float 的指针,然后对值进行取值。
重要的是,float
也存储在 .Net 中的 4 个字节中(与我们读过的 int
大小相同):
- 1 位符号
- 8 位指数
- 23 位尾数
为什么?从 int 到 float 的直接转换:
int num = ReadInt();
return (float)num;
不会恢复原始的 'float' 序列化为 4 字节,而是保留 4 字节 int 的整数值。
既然你说这段代码来自一个库,那么 ReadInt
很可能也是其他转换中使用的实用方法 - 即其他消耗 4 个字节的类型也可以使用 ReadInt
方法可能会做类似的 post-read 'reinterpretation' 读取的字节。
这种技术显然存在危险,例如如果返回的 int
占用的字节数不足以满足更大的数据类型,例如:
int num = ReadInt();
return *(double*) (&num); // Oops.