在C#中,我写了
unsafe void Main() {
float f = 3.14f;
int i = *(int*)&f;
}
是否可以将此代码翻译为F#?
我的理解是指针由nativeptr<'a>
类型表示,但是对于我的生活,我找不到地址引用&
和指针解引用*
运算符的等价物。我怀疑 NativePtr.get
可能是后者,但its implementation让我感到厌烦,因为我不太了解IL。
我知道BitConverter
和Marshal
,但我正在寻找一种在不复制内存的情况下实现位修改的方法。
答案 0 :(得分:6)
NativePtr.get
和set
函数以偏移量读写。如果需要逐字节读取,则使用它。如果您需要在零偏移处阅读,则可以使用read
和write
代替它们,它们的性能会略高一些。
采取&#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博士警告我们的那种过早优化。