F#的地址是&和指针解引用*函数?

时间:2016-03-22 22:36:36

标签: pointers f# inline unsafe byref

在C#中,我写了

unsafe void Main() {
  float f = 3.14f;
  int i = *(int*)&f;
}

是否可以将此代码翻译为F#?

我的理解是指针由nativeptr<'a>类型表示,但是对于我的生活,我找不到地址引用&和指针解引用*运算符的等价物。我怀疑 NativePtr.get可能是后者,但its implementation让我感到厌烦,因为我不太了解IL。

我知道BitConverterMarshal,但我正在寻找一种在不复制内存的情况下实现位修改的方法。

1 个答案:

答案 0 :(得分:6)

NativePtr.getset函数以偏移量读写。如果需要逐字节读取,则使用它。如果您需要在零偏移处阅读,则可以使用readwrite代替它们,它们的性能会略高一些。

采取&#34; raw&#34;地址(与byref<_>引用相对)称为&&see definition)。

但是还有一些技巧涉及,例如:你需要在变量mutable之前标记变量nativeptr<_>,你只需要存储nativeint值,你需要要将其转换为nativeptr<_>,加上nativeint值是强类型的,因此您需要通过open FSharp.NativeInterop let Main() = let mutable x: float = 3.1415 let floatPtr: nativeint = NativePtr.toNativeInt<float> &&x let intPtr: nativeptr<int> = floatPtr |> NativePtr.ofNativeInt<int> let asInt: int = NativeInterop.NativePtr.read intPtr asInt 等进行转换。

以下代码段将相当于您的C#代码(逐步完成并使用完整类型注释以提高清晰度):

open FSharp.NativeInterop

let Main() =
  let mutable x = 3.1415
  &&x |> NativePtr.toNativeInt |> NativePtr.ofNativeInt |> NativePtr.read<int>

或更紧凑的版本:

// val inline readAs : x:'a -> 'b when 'a : unmanaged and 'b : unmanaged
let inline readAs (x: 'a) : 'b =
  let mutable x' = x
  &&x' |> NativePtr.toNativeInt |> NativePtr.ofNativeInt |> NativePtr.read<'b>

let Main() =
  let i = readAs 3.1415 : int
  ()

或将其打包以供重复使用:

public class Practica_figura
{
    private float base;
    private float altura;
    private float radio;

    public Practica_figura()
    {
    }



    public void asignar(float ba, float al, float ra)
    {
      base = ba;
      altura = al;
      radio = ra;
    }

    //edits assuming you want inner classes
    class Figura
    {
      private float base, altura, radio;

      // you will need getters/setters for the variables
    }

    class Cuadrado extends Figura
    {
       // insert class logic here
    }

    class Triangulo extends Figura
    {
        // insert class logic here
    }
}

说完以上所有内容后,我完全赞同John Palmer和GuyCoder:请尽量不要这样做。这看起来就像Knuth博士警告我们的那种过早优化。