看看这个C代码:
int main()
{
unsigned int y = 10;
int x = -2;
if (x > y)
printf("x is greater");
else
printf("y is greater");
return 0;
}
/*Output: x is greater.*/
我理解为什么输出x更大,因为当计算机比较它们时,x被提升为无符号整数类型。 当x被提升为无符号整数时,-2变为65534,绝对大于10.
但是为什么在C#中,等效代码会产生相反的结果吗?
public static void Main(String[] args)
{
uint y = 10;
int x = -2;
if (x > y)
{
Console.WriteLine("x is greater");
}
else
{
Console.WriteLine("y is greater");
}
}
//Output: y is greater.
答案 0 :(得分:19)
在C#中,uint
和int
在比较之前都会升级为long
。
这在C#语言规范的4.1.5 Integral types
中有记录:
对于二进制+, - ,*,/,%,&,^,|,==,!=,>,<,> =和< =运算符,操作数将转换为type T,其中T是int,uint,long和ulong中的第一个,它们可以完全表示两个操作数的所有可能值。然后使用类型T的精度执行操作,结果的类型是T(或关系运算符的bool)。不允许一个操作数的类型为long,另一个操作数的类型为ulong,使用二元运算符。
由于long
是第一种可以完全代表所有int
和uint
值的类型,因此变量都会转换为long
,然后进行比较。
答案 1 :(得分:8)
在C#中,在int和uint的比较中,两个值都被提升为long值。
“否则,如果任一操作数的类型为uint而另一个操作数的类型为sbyte,short或int,则两个操作数都将转换为long类型。”
http://msdn.microsoft.com/en-us/library/aa691330(v=vs.71).aspx
答案 2 :(得分:0)
C和C#对于整数类型所代表的内容有不同的看法。有关C的观点的一些讨论,请参阅我的回答https://stackoverflow.com/a/18796084/363751。在C#中,整数是表示数字还是抽象代数环的成员在某种程度上取决于“已检查的算术”是打开还是关闭,但这只是控制越界计算是否应该抛出异常。通常,.NET框架将所有整数类型视为表示数字,除了允许执行某些越界计算而不抛出异常C#遵循其前导。
如果无符号类型代表代数环的成员,则添加例如-5到无符号2应该产生无符号值,当加到5时,它将产生2.如果它们代表数字,那么如果可能的话,将-5添加到无符号2将产生数字-3的表示。由于将操作数提升为Int64
将允许这种情况发生,这就是C#的作用。
顺便说一句,我不喜欢运算符(特别是关系运算符!)应该始终通过将它们的操作数提升为公共兼容类型来工作的概念,应该返回该类型的结果,并且应该接受而不会使任何运算符组合被唤醒晋升为普通类型。给定float f; long l;
,比较至少有三个合理的含义f==l
[它可以将l
转换为浮动,它可以将l
和f
转换为{ {1}},或者它可以确保double
是一个可以强制转换为f
的整数,并且在投出时它等于long
]。或者,编译器可以简单地拒绝这种混合比较。如果我使用druthers,编译器将被禁止将操作数转换为关系运算符,除非只有一个合理的含义。要求在任何地方可以隐式兑换的东西必须直接具有可比性,恕我直言是无益的。