是否可以确定 IntPtr 是指向 32 位还是 64 位浮点数?

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

如果在 .NET (C#) 中收到任意 IntPtr,是否可以确定它是指向 32 位还是 64 位浮点数并将其安全地转换为 .NET float类型?或者是否需要明确的类型知识?

IntPtr 从不 floatIntPtr 是一个 指针 。永远不要将 IntPtr 用于值 - 它仅用于指针。我已经看到很多使用 IntPtr 作为值的互操作尝试,但这总是一个糟糕的想法。

这意味着与非托管环境进行互操作 - 这样做通常意味着失去几乎所有类型的安全性 - 剩下的就是你的纪律。没有元信息可供参考,您必须知道所有内容的正确类型。您需要所有这些头文件是有原因的 - 缺少逆向工程,无法知道函数参数(甚至调用约定)是什么。

即使你得到了一个真正的指针(而不仅仅是一个被屏蔽为指针的值),你也无法知道提供给你的数据类型 - 它不在非托管互操作合同中的任何地方.

即使你真的在处理一个指向只能是 floatdouble 的值的指针,也没有办法知道你被传递了多少字节- 信息根本不存在;只有一个数字——内存指针。没有类型信息,甚至没有任何 length 信息。

在这样的时候,您会真正体会到 .NET 互操作的简单性 - 所有这些问题都在幕后得到处理。

不,没有办法神奇地确定指针指向什么 - 当你收到一个 IntPtr 时,你得到的只是内存地址 - 在从该地址读取数据之前你需要知道有多少字节阅读以及如何处理这些字节。

如果指针可能指向不同大小的数据,您将需要额外的信息来描述指针指向的数据。

在大多数情况下,不,这是不可能的。八字节(双精度)值的前四个字节在被解释为单精度值时具有一定意义。

但是,如果您有一些额外的知识(例如,值总是落在某个范围内/总是有限的),那么您可能能够区分 "four bytes are a single precision value" 和 "four bytes are a partial read of a double precision value"。要真正将其转化为检测算法,需要很多运气(关于您希望接收的数据的限制)。

在某些情况下,您可以从指针对齐推断出大小。四字节对齐绝对不是双精度值。但是,八字节对齐可以是精度,所以这是不可靠的。但它可能有助于避免读取超出页面边缘的额外字节并导致访问冲突。

如果你想沿着这条路走下去(意识到对于某些数据,你可能无法确定,维护也不会很有趣),你可以使用 Marshal.Copy 来将数据抓取到一个字节数组中,然后对其进行位测试以及 BitConverter 以将它们解释为不同精度的浮点值。一定要熟悉浮点数的IEEE编码,指数的偏置编码等

在另一个极端,如果你被传递给一个数据数组并且只给出以字节为单位的长度,而不是每个元素的 elements/size 的数量,你很有可能识别重复模式和推断精度。

底线:这不是构建部署软件的好方法。但是如果你正在编写一次性代码来处理特定的数据集,并且代码永远不会离开你的手,那么你就有成功的机会。

在不知道它指向的值的更多信息的情况下,无法确定类型。最好的办法是检查前 32 位以确定它是否是 32 位浮点格式中实际使用的位模式。有一些未使用的位模式,所以如果您找到其中一个,您知道它必须是 64 位数字,否则您仍然不知道。

如果您对数据可以包含的数字范围有所了解,实际上就可以确定格式。例如,如果您知道指数仅限于几个值,则您可以确定它是 8 位指数(32 位数字)还是 11 位指数(64 位数字)。