我正在读这个post,我想知道,如果CLR将字节和Int16转换为Int32用于算术运算,它是否在64位模式下运行时将所有字节,Int16和Int32转换为Int64?
编辑:由于以下循环:
for (short i = 0; i < 10; i++) {
// ...
}
会在IL中产生类似的东西:
Int16 i = 0;
LOOP:
Int32 temp0 = Convert_I16_To_I32(i); // !!!
if (temp0 >= 10) goto END;
...
Int32 temp1 = Convert_I16_To_I32(i); // !!!
Int32 temp2 = temp1 + 1;
i = Convert_I32_To_I16(temp2); // !!!
goto LOOP;
END:
以下循环:
for (int i = 0; i < 10; i++) {
// ...
}
在64位架构上产生类似的东西吗?
Int32 i = 0;
LOOP:
Int64 temp0 = Convert_I32_To_I64(i); // !!!
if (temp0 >= 10) goto END;
...
Int64 temp1 = Convert_I32_To_I64(i); // !!!
Int64 temp2 = temp1 + 1;
i = Convert_I64_To_I32(temp2); // !!!
goto LOOP;
END:
答案 0 :(得分:3)
实际上,CLR没有做任何事情:C#编译器。你看,CLR确实支持Byte
和Int16
类型,但它不支持对它们进行算术运算,所以要对Byte
和Int16
执行算术运算,它们最初应该被转换为最小支持类型(Int32
)。
这种转变的行为取决于语言。 C#团队选择自动将这些类型的所有计算转换为Int32
,因此您可以看到相应的IL。 VB.NET选择保存类型信息,因此代码中没有看到类型转换,但是在这种情况下IL代码更麻烦:它们必须使用转换为Int32
,检查溢出是否已经发生,然后从Int32
。
所以,它取决于语言。 C#规范明确规定算术运算与大小无关,因此在每个平台上您都会看到转换为Int32
。 CLR确实指定Int32类型总是占用4个字节的内存空间,但它不受此限制:CLR还支持native int
类型,其大小取决于平台。 C#不允许这样做,因此您只能在unsafe
部分使用此类型。
附:为清楚起见,省略了有符号/无符号的变量
P.P.S. IntPtr
是安全的,但它的实现依赖于平台:IntPtr.Size在32位上是4个字节,在64位上是8个字节