11

我发现 CIL 编译器允许 type native float. 但是,CLR 不允许这样做。它有什么用处吗?它的大小是多少?是否有对应的 .NET 类型?我试图将它实现为伪原始类型:

.class public sequential ansi serializable sealed beforefieldinit NativeFloat
  extends System.ValueType
{
  .field assembly native float m_value
}

但是,CLR 不支持这种类型。感谢您的帮助。

编辑:如果你有兴趣,它的 CorElementType 是 26 (0x1a, R)。

4

2 回答 2

5

来自 CIL ECMA 规范,I.12.1.1 原生大小:原生 int、原生 unsigned int、O 和 &

本机大小类型(本机 int、本机 unsigned int、O 和 &)是 CLI 中用于延迟选择值大小的一种机制。这些数据类型作为 CIL 类型存在;但是,CLI 将每个映射到特定处理器的本机大小。(例如,数据类型在 Pentium 处理器上映射到 int32,但在 IA64 处理器上映射到 int64。)因此,大小的选择推迟到 JIT 编译或运行时,此时 CLI 已初始化并且架构已知. 这意味着字段和堆栈帧偏移量在编译时也是未知的。

现在,话虽如此,native float(相对于native int)在 ECMA 规范中没有一次提及。我能找到的唯一证据是在一些开源 CIL 汇编器中,它们会抛出异常,指出它们无法为native float.

如果微软的 CIL 编译器确实接受这种类型,我想这是微软打算实现的功能,但最终没有放入 MSIL(CIL 的前身)。此外,如果汇编程序确实生成了操作码而不是错误消息,我可以想象(尽管这也是推测)可能存在 Microsoft 的 CLR 的变体(可能是 .NET Micro Framework 或特定版本的 Silverlight,或其他东西)支持操作码。

另请注意,在上面的规范中,提到了 CLI。CLR 只是 Microsoft 对 CLI 的实现。

ECMA 规范确实提到了本机浮点类型,但它不是native float

F,浮点值(float32、float64 或底层硬件支持的其他表示)

于 2012-12-19T21:37:08.427 回答
5

CLI 规范 Ecma 335 定义了三种浮点类型。Float32、float64 和 F。前两个是名义类型,第三个是表示类型,即 IL 中的“本机浮点”类型。

第 I.12.1.3 节,“浮点数据类型的处理”给出了理由:

浮点数(静态、数组元素和类的字段)的存储位置是固定大小的。支持的存储大小为 float32 和 float64。在其他任何地方(在评估堆栈上,作为参数、作为返回类型和作为局部变量)浮点数都使用内部浮点类型表示。在每个这样的实例中,变量或表达式的标称类型是 float32 或 float64,但其值可以在内部用额外的范围和/或精度表示。内部浮点表示的大小取决于实现,可以变化,并且应具有至少与所表示的变量或表达式一样大的精度。

这在当前的抖动实现中实际上并不存在,参数和局部变量实际上是 float32 或 float64。但它有一些先例,他们首先考虑这一点的可能原因是,英特尔处理器中的内部 FPU 寄存器是 80 位的。这是许多个月前英特尔设计 8087 协处理器时做出的设计决定。

这个想法在纸面上听起来非常好,它允许更精确地存储中间计算结果,以便计算的最终结果更准确。然而,毫无疑问,英特尔犯了十亿美元的错误,FPU 无​​法优化并且仍然允许一致的浮点结果。问题是内部 FPU 寄存器是有限的资源,只有 8 个。它也被实现为堆栈,处理起来很尴尬。如果涉及计算,则不可避免地需要将中间结果溢出到内存中。将 80 位值截断为 64 位。如果计算容易丢失很多有效数字,那么对代码的微小更改会在计算结果中产生很大差异。或者一般来说让程序员感到不安,因为第 16 位数字不是

好吧,这是一个大错误,也是 SO 大量问题的根源。当英特尔实现下一代浮点硬件时,这个想法被废弃了,XMM 和 YMM 寄存器是 64 位的。真正的寄存器,而不是堆栈。x64 抖动使用它们。让您的程序在 64 位模式下运行会产生与在 32 位模式下运行时不同的结果。还需要十年时间才能停止伤害。

于 2012-12-19T21:45:08.880 回答