是否有可能确定IntPtr是指向32位浮点数还是64位浮点数?
本文关键字:浮点数 32位 64位 有可能 IntPtr 是否 | 更新日期: 2023-09-27 18:10:29
如果在。net (c#)中接收到任意IntPtr
,是否有可能确定它是指向32位还是64位浮点数并安全地将其转换为。net float
类型?还是需要对类型有明确的了解?
在大多数情况下,这是不可能的。当将8字节(双精度)值的前四个字节解释为单精度值时,它们具有一定的含义。
然而,如果你有一些额外的知识(例如,值总是落在一定范围内/总是有限的),那么你可能能够区分"四个字节是单精度值"answers"四个字节是双精度值的部分读取"。它将需要很多运气(关于您期望接收的数据的限制)才能真正将其转化为检测算法。
在某些情况下,您可以从指针对齐推断大小。四字节对齐绝对不是双精度值。但是,八字节对齐可能是精确的,因此这并不可靠。但是,它可以帮助您避免读取超出页面边缘的额外字节并导致访问冲突。
如果您想沿着这条路径前进(要知道,对于某些数据,您可能无法确定,并且维护不会很有趣),您可以使用Marshal.Copy
将数据捕获到字节数组中,然后对其进行位测试,以及BitConverter
将它们解释为不同精度的浮点值。一定要熟悉浮点数的IEEE编码、指数的偏置编码等。
在另一种极端情况下,如果传递给你一个数据数组,并且只给出长度(以字节为单位),而不给出元素的数量/每个元素的大小,那么你很有可能识别出重复模式并推断出精度。
底线:这不是构建用于部署的软件的好方法。但是,如果您正在编写一次性代码来处理特定的数据集,并且代码永远不会离开您的手,那么您有可能成功。
不,没有办法神奇地确定一个指针指向什么——当你收到一个IntPtr
,你得到的只是内存地址——你需要在从那个地址读取数据之前知道要读取多少字节以及如何处理这些字节。
如果指针可能指向不同大小的数据,则需要额外的信息来描述指针所指向的数据
IntPtr
is never a float
。IntPtr
是指针。永远不要将IntPtr
用于值,它只用于指针。我曾见过不少使用IntPtr
作为值的互操作尝试,但这总是一个糟糕的想法。
这意味着与非托管环境进行互操作——这样做通常意味着失去几乎所有的类型安全性——剩下的就是您的规程了。没有元信息可以参考,你必须知道所有东西的正确类型。需要所有这些头文件是有原因的——除非进行逆向工程,否则没有办法知道函数的参数(甚至调用约定)是什么。
即使你得到了一个真正的指针(而不仅仅是一个被掩盖成指针的值),你也没有办法知道给你的数据类型——它不在非托管互操作契约的任何地方。
即使你真的在处理一个指向float
或double
值的指针,也没有办法知道你传递了多少字节——信息根本不存在;只有一个数字——内存指针。没有类型信息,甚至没有长度信息。
在这样的时候,你才真正体会到。net互操作是多么简单——所有这些问题都在幕后得到了解决。
如果不知道它所指向的值的更多信息,就不可能确定类型。您能做的最好的事情是检查前32位,以确定它是否是在32位浮点格式中实际使用的位模式。有几个位模式是未使用的,所以如果你发现其中一个,你知道它必须是64位的数字,否则你仍然不知道。
如果您知道数据可以包含的数字范围,那么实际上可以确定格式。例如,如果您知道指数仅限于几个值,则可以确定它是具有8位指数(32位数字)还是11位指数(64位数字)。