unsigned int (c++)和uint (c#)的区别

40

以下是 C# 代码:

   static void Main(string[] args)
    {
        uint y = 12;
        int x = -2;
        if (x > y)
            Console.WriteLine("x is greater");
        else
            Console.WriteLine("y is greater");
    }

这是C++代码:

int _tmain(int argc, _TCHAR* argv[])
{
unsigned int y = 12;
int x = -2;
if(x>y)
    printf("x is greater");
else
    printf("y is greater");

return 0;
}

两者输出的结果不同。我是否漏掉了一些基本的东西?有什么想法吗?


可能是[有符号/无符号比较]的重复问题。 (https://dev59.com/zG035IYBdhLWcg3wcvmS) - user541686
4
提示:在进行比较时,始终确保两个值是相同类型的。 - RvdK
@Mehrdad:这个问题是关于为什么在C++中使用有符号/无符号比较运算符<、>、>=或<=时会导致编译器警告,但使用==运算符时却不会。这是一个完全不同的问题,它的答案与这个问题的答案几乎没有关系。 - Keith Irwin
3个回答

48

C++和C#是不同的编程语言。它们在比较时处理类型提升的规则不同。

在C++和C中,它们通常被视为无符号进行比较。这称为“保留无符号值”。传统上,C++和C编译器使用“保留无符号值”,并且此用法已在C++标准和K&R中指定。

在C#中,它们都被转换为有符号长整型,然后进行比较。这称为“保留值”。C#指定了保留值。

ANSI C也指定了保留值,但只适用于shorts和chars。短整型和字符型(有符号和无符号)以保留值方式提升为整型,然后进行比较。因此,如果将无符号短整型与有符号短整型进行比较,则结果会像C#示例一样。每当执行向更大尺寸的转换时,都会以保留值方式进行,但如果两个变量具有相同的尺寸(而不是shorts或chars)并且任一变量是无符号的,则在ANSI C中将作为无符号数量进行比较。在comp.lang.c FAQ中对两种方法的优劣进行了很好的讨论。


1
C++标准确实提供了处理此情况的规则,当涉及到intunsigned int时,两个操作数都会被转换为unsigned int - fefe
3
“通常将它们进行比较,好像它们都没有签名...”每个C或C++编译器需要在这种情况下将int转换为unsigned int。这是由正式标准规定的,因为一个无符号数可以保存比int更大的值。 - Gunther Piez
感谢您的评论。我仔细检查了一下,尽我所能,您是正确的。因此,我已经更改了答案。我还找到了有关ANSI C标准转换及其工作方式的更多信息(仅在进行大小增加转换时保留值)。因此,它已更新以反映这一点。 - Keith Irwin
我移除了负面评价。现在这个答案更加精准了。 - Gunther Piez
C语言的行为可以理解为,无符号整数类型代表着一个抽象代数环的成员,而不是数值量。向抽象环中添加数字会产生另一个环,有点像将数字添加到指针中产生另一个指针一样(尽管环元素也可以相互添加,而指针则不能)。 - supercat

12
在C++中,当你比较一个unsigned int和一个signed int时,signed int会转换为unsigned int。将一个负的signed int转换为unsigned int是通过添加UINT_MAX + 1来完成的,这比12要大,因此结果也就出现了变化。
在C#中,如果你得到了相反的结果,那么这意味着在C#中两个表达式都被转换为signed intsigned longlongSystem.Int641 ,然后再进行比较。
在C++中,你的编译器必须已经给出了警告:

warning: comparison between signed and unsigned integer expressions

规则:
始终认真对待编译器发出的警告!

1正如svick在评论中指出的那样。


4
在C#中,表达式会被转换为带符号的长整型(longSystem.Int64)。 - svick
据我所知,在C++标准中没有警告信息的要求,只有错误信息。“必须” => “应该”? - dalle

4

我不知道C#的标准,但在C++标准中,关系运算符的两个操作数都会应用通常的算术转换

[......enum, floating point type involed......] 

— Otherwise, the integral promotions (4.5) shall be performed on both operands.
  Then the following rules shall be applied to the promoted operands:

    — If both operands have the same type, no further conversion is needed.

    — Otherwise, if both operands have signed integer types or both have
      unsigned integer types, the operand with the type of lesser integer
      conversion rank shall be converted to the type of the operand with
      greater rank.

    — Otherwise, if the operand that has unsigned integer type has rank
      greater than or equal to the rank of the type of the other operand, the
      operand with signed integer type shall be converted to  the type of the
      operand with unsigned integer type.

    — Otherwise, if the type of the operand with signed integer type can
      represent all of the values of the type of the operand with unsigned
      integer type, the operand with unsigned integer type shall be converted
      to the type of the operand with signed integer type.

    — Otherwise, both operands shall be converted to the unsigned integer type 
      corresponding to the type of the operand with signed integer type.
因此,当将unsigned intint进行比较时,int将被转换为unsigned int,并且-2在转换为unsigned int时会变成一个非常大的数字。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接