简体   繁体   中英

Is it possible to determine if an IntPtr is pointing to a 32-bit or to a 64-bit float?

If an arbitrary IntPtr is received in .NET (C#), is it possible to determine if it is pointing to a 32-bit or 64-bit float and safely convert it to the .NET float type? Or is explicit knowledge of the type required?

IntPtr is never a float . IntPtr is a pointer . Do not use IntPtr for values, ever - it is only for pointers. I've seen quite a few attempts at interop using IntPtr for values, but that's a terrible idea, always.

This kind of implies interoperating with an unmanaged environment - and doing that usually means losing pretty much all type safety - all that's left is your discipline. There is no meta information to go by, you must know the proper types of everything. There's a reason why you need all those header files - short of reverse engineering, there is no way to know what a functions arguments (or even the calling convention) are.

Even if you are being given a real pointer (and not just a value masked as a pointer), you have no way of knowing the data type of what's being given to you - it's not anywhere in the unmanaged interop contract.

Even if you really are dealing with a pointer to a value that can only ever be either a float or a double , there is no way to know how many bytes you are being passed - the information simply isn't there; just a single number - the memory pointer. There is no type information, there isn't even any length information.

It's times like these where you really appreciate just how simple .NET interop is - all those issues are taken care of behind the scenes.

No, there's no way to magically determine what a pointer points to - when you receive an IntPtr , all you get is the memory address - you need to know before reading data from that address how many bytes to read and how to treat those bytes.

If it's possible that the pointer points to data of different sizes, you'll need extra information that describes the data pointed by the pointer.

In the most general case, no it isn't possible. The first four bytes of an eight byte (double precision) value have some meaning when interpreted as if they were a single precision value.

However, if you have some additional knowledge (eg the values always fall within a certain range / are always finite) then you may be able to differentiate between "four bytes are a single precision value" and "four bytes are a partial read of a double precision value". It's going to need a lot of luck (regarding the restrictions on the data you expect to receive) to actually turn this into a detection algorithm.

In some cases, you may be able to infer size from the pointer alignment. Four byte alignment is definitely not a double precision value. Eight byte alignment can be either precision, though, so this isn't reliable. But it may be useful to save you from reading extra bytes beyond the edge of a page and causing an access violation.

If you want to head down this path (being aware that for some data, you might not be able to decide for sure, and maintenance is not going to be fun), you can use Marshal.Copy to grab the data into a byte array, and then do bit tests on that as well as BitConverter to interpret them as floating-point values of different precisions. Be sure to get familiar with IEEE encoding of floating-point numbers, biased encoding of exponents, etc.

At the other extreme, if you're being passed an array of data and given only the length in bytes, but not the number of elements/size of each element, you have a very good chance of identifying the repetition pattern and deducing the precision.

Bottom line: This isn't a good way to build software for deployment. But if you are writing throw-away code to deal with a particular dataset, and the code will never leave your hands, there's a chance you can succeed.

Without knowing anything more about the value that it points to, it's not possible to determine the type. The best that you could do would be to examine the 32 first bits to determine if it is a bit pattern that is actually used in the 32 bit floating point format. There are a few bit patterns that are unused, so if you find one of those you know that it has to be a 64 bit number, otherwise you still don't know.

If you know something about the range of numbers that the data can have, it could actually be possible to determine the format. If you for example know that the exponent is limited to a few values, you may be able to determine if it has an 8 bit exponent (32 bit number) or an 11 bit exponent (64 bit number).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM