14

看看这个 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. 
4

3 回答 3

20

在 C# 中,两者都uint被提升为intalong之前的比较。

这记录在4.1.5 Integral typesC# 语言规范中:

对于二进制 +、–、*、/、%、&、^、|、==、!=、>、<、>= 和 <= 运算符,操作数转换为 T 类型,其中 T 是第一个int、uint、long 和 ulong 可以完全表示两个操作数的所有可能值。然后使用类型 T 的精度执行操作,结果的类型是 T(或关系运算符的 bool)。对于二元运算符,不允许一个操作数为 long 类型而另一个为 ulong 类型。

由于long是第一种可以完全表示所有intuint值的类型,因此变量都转换为long,然后进行比较。

于 2013-08-06T23:32:57.153 回答
9

在 C# 中,在 int 和 uint 之间的比较中,两个值都被提升为 long 值。

“否则,如果其中一个操作数是 uint 类型,而另一个操作数是 sbyte、short 或 int 类型,则两个操作数都将转换为 long 类型。”

http://msdn.microsoft.com/en-us/library/aa691330(v=vs.71).aspx

于 2013-08-06T23:33:11.687 回答
2

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,或者它可以确保 that是一个可以转换为的整数,并且当转换时它等于fdoubleflongl]。或者,编译器可以简单地拒绝这种混合比较。如果我有 druthers,编译器将被禁止将操作数转换为关系运算符,除非只有一个合理的含义。要求在任何地方都可以隐式转换的东西必须是直接可比的,恕我直言是没有帮助的。

于 2013-09-13T22:51:22.987 回答