2016-03-22 1 views
3

В C#, я пишуИмеет ли F # адрес и функции разыменования * и?

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

Можно ли перевести этот код на F #?

Я понимаю, что указатель представлен nativeptr<'a> типа, но я для жизни меня я не могу найти эквивалент ссылки адреса & и указатель разыменования * операторов. I подозреваемыйNativePtr.get может быть последним, но its implementation убегает от меня, так как я не очень хорошо разбираюсь в ИЛ.

Я знаю о BitConverter и Marshal, но я ищу способ реализации бит-манипуляции без копирования памяти.

+0

@GuyCoder: Я хочу посмотреть * бит * существующего поплавка, как если бы это был int. – kkm

+0

Какова цель этого? Это, безусловно, плохая идея написать такой код. –

+0

@JohnPalmer: Это совершенно не относится к вопросу, но намерение - хеширование. – kkm

ответ

5

NativePtr.get и set функции чтения и записи со смещением. Если вам нужно прочитать байты по байт, используйте это. Если вам нужно читать с нулевым нулевым значением, вместо этого вы можете использовать read и write, они будут немного более результативными.

Оператор для взятия «необработанного» адреса (в отличие от ссылки byref<_>) называется && (see definition).

Но есть еще некоторые хитрости участвуют, например: вы должны пометить переменную mutable, прежде чем взять его адрес, вы не можете просто хранить значение nativeptr<_>, вам нужно преобразовать его в nativeint, плюс nativeptr<_> значения сильно типизированных, так что вам нужно преобразовать между ними через nativeint и т.д.

следующий фрагмент кода будет делать эквивалент вашей C# код (шаг за шагом и с полными аннотациями типа для повышенной четкости):

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 

Или более компактный v ersion:

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 
() 

Сказав все вышесказанное, я полностью согласен с Джоном Палмером и GuyCoder: , пожалуйста, не делайте этого, если вообще возможно. Это похоже на то, что преждевременная оптимизация, о которой предупредил нас доктор Кнут.

+0

Для записи это доктор Кнут. – kemiller2002

+0

Хорошо, исправлено .. –

+0

Я согласен, что не стоит этого делать, если они не знают, что делают. Тем не менее, есть очень веские причины сделать это, если вы знаете, что делаете, и нуждаетесь в этом. Если вам понадобятся указатели, посмотрите [SafeHandles] (https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle (v = vs.110) .aspx). Если вам нужно сделать много манипуляций с низким уровнем, посмотрите на [System.Runtime.InteropServices] (https://msdn.microsoft.com/en-us/library/system.runtime.interopservices (v = vs.100) .aspx) –

Смежные вопросы