gpt4 book ai didi

.net - 将 int32 添加到 64 位 native int 的结果?

转载 作者:行者123 更新时间:2023-12-03 23:54:28 28 4
gpt4 key购买 nike

添加 int32 时到 64 位 native int , CLR 是对 32 位整数进行符号扩展还是零扩展?最重要的是:它根据什么信息做出这个选择?

我正在编写一个 .NET 编译器并通读了 ECMA 规范,但找不到答案。

The CLI supports only a subset of these types in its operations upon values stored on its evaluation stack: int32, int64, and native int.
-- ECMA 335, Section I 12.1: Supported data types



由于计算堆栈上的值没有关于它们的符号性的信息,因此操作数的符号性很重要的指令有两种变体:一种用于有符号整数,一种用于无符号整数。 add , submul只要操作数的大小相同,指令(不检查溢出的指令)就不需要关心操作数的符号性,因此只有一个变体。但是,操作数并不总是相同的大小......

ECMA 335 , 第 III 节 1.5:操作数类型表指出 int32和一个 native int可以加、减、乘、除。结果又是 native int .在 64 位系统上, native int是 64 位宽。
ldc.i4.0            // Load int32 0
conv.i // Convert to (64-bit) native int
ldc.i4.m1 // Load int32 -1
add // Add native int 0 and int32 0xFFFFFFFF together

那么这里的结果是什么?请注意,根据规范,运行时不需要跟踪堆栈上值的确切类型或签名:它只知道 int32 , int64native int (以及其他一些与此处无关的内容)。

我会想象 IntPtrUIntPtr算术,因为它在内部表示为本地整数,也将使用这种加法。但是,ILSpy 显示添加 IntPtr和一个 Int32在 C# 中调用 IntPtr 上的重载 + 运算符类,它只接受一个签名的 Int32论据。

直接在 CIL 中执行(使用 add 指令)也表明整数被解释为有符号的。它也应该在 Mono 中实现,但我找不到任何引用资料来支持我的发现。

最佳答案

将两个相同位大小的值相加时,符号性无关紧要。例如,将 32 位 -10 ( 0xfffffff6 ) 添加到 32 位 10 ( 0x0000000a ) 将正确产生 0。因此,只有一个 add CIL(通用指令语言)中的指令。

但是,当添加两个不同位大小的值时,符号性确实很重要。例如,将 32 位 -10 添加到 64 位 10 会导致 4294967296 ( 0x100000000 ) 在完成无符号时和 0 在有符号时。

CIL add指令允许添加一个本地整数和一个 32 位整数。 native 整数可以是 64 位(在 64 位系统上)。 测试表明 add将 32 位整数视为有符号整数,并对其进行符号扩展。 This is not always correct可以考虑 a bug .微软目前不会修复它。

因为溢出检查取决于操作数是被视为无符号还是有符号,所以 add.ovf 有两种变体。 :add.ovf (签名)和 add.ovf.un (未签名)。但是,当将 32 位整数添加到 native 整数时,这些变体也可以正确地对较小的操作数进行零符号扩展。

因此,根据 C# 的溢出检查设置,添加 native 整数和无符号 32 位整数可能会产生不同的结果。显然,我无法弄清楚这一事实是 CIL 语言设计中的错误或疏忽的结果。

关于.net - 将 int32 添加到 64 位 native int 的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14188693/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com