int在C和C#中提升为无符号int

本文关键字:int 无符号 | 更新日期: 2023-09-27 18:26:49

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

int在C和C#中提升为无符号int

在C#中,uintint在比较之前都会升级为long

这在C#语言规范的4.1.5 Integral types中有记录:

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

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

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

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

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

C和C#对积分类型的表示有不同的看法。看看我的答案https://stackoverflow.com/a/18796084/363751以便对C的观点进行一些讨论。在C#中,整数是表示数字还是抽象代数环的成员,在某种程度上取决于"检查算术"是打开还是关闭,但这只是控制越界计算是否应该抛出异常。一般来说,.NET框架将所有整数类型视为表示数字,除了允许执行一些越界计算而不引发异常之外,C#也紧随其后。

如果无符号类型表示代数环的成员,则将-5添加到无符号2应产生无符号值,当将其添加到5时,将产生2。如果它们表示数字,那么如果可能的话,在无符号的2上加上-5应该会得到数字-3的表示。由于将操作数提升为Int64将允许这种情况发生,所以C#就是这么做的。

顺便说一句,我不喜欢运算符(尤其是关系运算符!)应该始终通过将其操作数提升为通用兼容类型来工作,应该返回该类型的结果,并且应该接受任何可以提升为通用类型的运算符组合而不发出刺耳的声音。给定float f; long l;,比较f==l至少有三个合理的含义[它可以将l强制转换为float,可以将lf强制转换为double,或者它可以确保f是一个可以强制转换为long的整数,并且当强制转换时它等于l]。或者,编译器可以简单地拒绝这种混合比较。如果我真的这么做了,编译器将被禁止将操作数强制转换为关系运算符,除非只有一个合理的含义。要求在任何地方都可以隐含转换的东西必须是直接可比的,IMHO是没有帮助的。