int32
64ビットにを追加する場合native int
、CLRは32ビット整数を符号拡張しますか、それともゼロ拡張しますか?そして最も重要なのは、どのような情報に基づいてこの選択を行うのかということです。
.NETコンパイラを作成していて、ECMA仕様をよく読んでいますが、答えが見つかりませんでした。
int32
CLIは、評価スタックに格納されている値、、、int64
およびの操作で、これらのタイプのサブセットのみをサポートしますnative int
。
--ECMA 335、セクションI 12.1:サポートされているデータ型
評価スタックの値には符号付きの情報がないため、オペランドの符号が重要な命令には、符号付き整数用と符号なし整数用の2つのバリアントがあります。、および命令(オーバーフローをチェックしない命令)は、オペランドが同じサイズである限り、オペランドの符号を気にする必要はありません。したがって、バリアントは1つだけですadd
。ただし、オペランドは常に同じサイズであるとは限りません。sub
mul
ECMA 335、セクションIII 1.5:オペランドタイプの表には、anint32
とanative int
を加算、減算、乗算、および除算できると記載されています。結果は再びnative int
です。64ビットシステムでは、anative 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
およびint64
(native int
およびここでは関係のない他のいくつか)のみを認識します。
算術演算は、内部的にネイティブintとして表されるため、この種の加算も使用するIntPtr
と思います。UIntPtr
ただし、ILSpyは、C#にanIntPtr
とaを追加するとInt32
、クラスでオーバーロードされた+演算子が呼び出され、符号付き引数IntPtr
のみを受け入れることを示しています。Int32
(命令を使用して)CILで直接add
実行することは、整数が署名されていると解釈されることも示します。これもMonoで実装されているはずですが、調査結果を裏付けるための参照が見つかりませんでした。