C# 在int到float的不安全转换中,什么';s是*(float*)(&;num)吗?

C# 在int到float的不安全转换中,什么';s是*(float*)(&;num)吗?,c#,unsafe,C#,Unsafe,我正在编写一个流API,它使用了很多东西来处理BigEndian/LittleEndian和无符号与有符号的转换。我有下面的代码,它可以工作。但是我想知道它在做什么,能不能请一些ELI5(像我一样解释一下) int num=ReadInt(); 返回*(浮点*)(&num); 公共int ReadInt() { 返回 (_memoryStream.ReadByte()只是一步一步地解释一下: &获取指向num中包含的对象的指针 (float*)将此指针强制转换为浮点指针 *取消引用此指针,即获取

我正在编写一个流API,它使用了很多东西来处理BigEndian/LittleEndian和无符号与有符号的转换。我有下面的代码,它可以工作。但是我想知道它在做什么,能不能请一些ELI5(像我一样解释一下)

int num=ReadInt();
返回*(浮点*)(&num);
公共int ReadInt()
{
返回

(_memoryStream.ReadByte()只是一步一步地解释一下:

  • &
    获取指向
    num
    中包含的对象的指针
  • (float*)
    将此指针强制转换为浮点指针
  • *
    取消引用此指针,即获取此指针处的值
  • 总的来说,这将以浮点形式返回字节流中最近的四个字节

    如果我冒险猜测一下,这是这样写的,因为
    int
    float
    之间的直接转换,而不是读取字节的表示,这可能不是期望的行为。

    &num
    --“num
    的地址”,它是指向整数的指针

    (float*)&num
    -“num的地址,转换为指向float的指针。”

    这是
    num
    的内存地址,但编译器将其内容解释为浮点数,而不是整数

    *(float*)&num
    num
    的地址”的内容,转换为指向float的指针-换句话说,获取
    num
    占用的内存,并将其作为浮点数读取

    因此,如果要读入字节0x40、0x10、0x00、0x00, 您将在内存位置“num”中获得整数0x40100000=1074790400 “num”的地址将转换为指向float的指针,并且 你可以提取它的内容。当解释时,常量0x40100000
    作为一个浮点数,是2.25,这是您将返回的。

    假设这是不安全的C#code,
    ReadInt
    通过将每个字节分别移位24位、16位、8位和0,将4个字节从BigEndian顺序字节流加载到
    int
    的4个字节中(与
    C
    等语言不同,
    .Net
    中的
    int
    保证为4字节,与平台无关)

    正如您所猜测的,这可能是“endian不可知”库的一部分,该库使用其专有的二进制序列化格式。几乎可以肯定会有一个相应的
    SaveInt
    方法,该方法同样会将一个4字节的int按相应的字节顺序保存到流中

    其他人已经解释过,代码:

    int num = ReadInt();
    return *(float*) (&num);
    
    将假定的32位
    int
    (存储在内存中)的前4个字节重新解释为单精度浮点,存储为IEEE 754格式浮点布局。使用的技术是将指向int地址的指针重新转换为指向浮点的指针,然后取消该值

    重要的是,
    float
    也存储在.Net中的4个字节中(与我们读到的
    int
    大小相同):

    • 1位符号
    • 8位指数
    • 23位尾数
    为什么?从int到float的直接转换:

    int num = ReadInt();
    return (float)num;
    
    将不会恢复序列化为4字节的原始“float”,而是保留4字节int的整数值

    由于您说此代码来自库,因此
    ReadInt
    很可能也是其他转换中使用的实用方法-即,消耗4字节的其他类型也可以使用
    ReadInt
    方法对读取的字节进行类似的读后“重新解释”

    这种技术显然存在危险,例如,如果返回的
    int
    占用的字节数不足以满足更大的数据类型,例如:

    int num = ReadInt();
    return *(double*) (&num); // Oops.
    

    好吧,这真是太聪明了。我最终会探索如何重写它们以确保安全,但现在我所有的单元测试都通过了,我知道它在做什么。谢谢!进一步检查后,用于.NET的内置类BitConverter似乎也在做同样的事情。
    int num = ReadInt();
    return *(double*) (&num); // Oops.