unsigned int b=2;
int a=-2;
if(a>b)
printf("a>b");
else
printf("b>a");
输出:a> b
int b=2;
int a=-2;
if(a>b)
printf("a>b");
else
printf("b>a");
输出:b> a
请有人解释输出
答案 0 :(得分:1)
在第一种情况下,两个操作数都转换为unsigned int
,转换后的a
将为UINT_MAX-1
,它比b
更大因此输出。
除非您了解arithematic转换的语义,否则不要比较有符号和无符号整数,结果可能会让您感到惊讶。
答案 1 :(得分:0)
以下摘自The C Programming Language
Kernighan
和Ritchie
- 2.7 Type Conversions
- 第44页;该页面的后半部分详细解释了相同的场景。下面有一小部分供您参考。
当涉及unsigned
个操作数时,转换规则很复杂。问题是signed
和unsigned
值之间的比较取决于机器,因为它们取决于各种integer
类型的大小。例如,假设int
长16位,long
为32位。然后是-1L < 1U
,因为1U
是int
,会被提升为signed long
。但是-1L > 1UL
,因为-1L
被提升为unsigned long
,因此似乎是一个更大的正数。
答案 2 :(得分:0)
当比较有符号值和无符号值时,并且无符号值不能全部用有符号类型表示时,则带符号的操作数将提升为无符号。这是通过一个公式来完成的,该公式相当于对2-s补码位模式的重新解释。
好吧,负数有很多高位设置......
由于你的操作数都是相同的等级,所以只需比较无符号位模式。
所以-2用111111..110表示,比最大可能值小1,当解释为无符号时,它很容易击败2。
答案 3 :(得分:0)
您需要了解C中的运算符操作以及C提升和转换规则。它们在C标准中解释。一些摘录加上我的评论:
6.5.8关系运营商
的语法强>
1关系表达式:
移位表达
关系表达&lt;移位表达
关系表达&gt;移位表达
relational-expression&lt; = shift-expression
relational-expression&gt; = shift-expression
<强>语义强>
3如果两个操作数都有算术类型,则通常的算术转换为
进行。强>
大多数操作员在实际操作(加法,乘法,比较等)之前包括这个“通常的算术转换”步骤。 - Alex
6.3.1.8常规算术转换
1许多期望算术类型操作数的运算符会导致转换并产生结果 以类似的方式输入类型。目的是确定操作数的通用实数类型 和结果。对于指定的操作数,将转换每个操作数,而不更改类型 域,对应的实类型是常见的实类型。除非 另外明确说明,常见的真实类型也是相应的实际类型 结果,其类型域是操作数的类型域,如果它们是相同的, 否则复杂。这种模式称为通常的算术转换:
首先,如果任一操作数的相应实数类型是long double,则另一个 操作数在不更改类型域的情况下转换为其类型的类型 相应的实际类型是长双。
否则,如果任一操作数的相应实数类型为double,则为另一个 操作数在不更改类型域的情况下转换为其类型的类型 相应的实际类型是双倍。
否则,如果任一操作数的相应实数类型为float,则为另一个 操作数在不更改类型域的情况下转换为其类型的类型 相应的真实类型是浮动。
否则,将对两个操作数执行整数提升。那么 以下规则适用于提升的操作数:
如果两个操作数具有相同的类型,则无需进一步转换。
否则,如果两个操作数都有有符号整数类型或两者都有无符号 整数类型,具有较小整数转换等级类型的操作数是 转换为具有更高等级的操作数的类型。
否则,如果具有无符号整数类型的操作数的等级大于或等于 等于另一个操作数的类型的等级,然后是操作数 有符号整数类型转换为带有unsigned的操作数的类型 整数类型。
否则,如果带有符号整数类型的操作数的类型可以表示 那么,带有无符号整数类型的操作数类型的所有值 具有无符号整数类型的操作数将转换为该类型 带有符号整数类型的操作数。
否则,两个操作数都将转换为无符号整数类型 对应于带有符号整数类型的操作数的类型。
6.3.1.3有符号和无符号整数
当整数类型的值转换为_Bool以外的另一个整数类型时,如果该值可以用新类型表示,则它将保持不变。
否则,如果新类型是无符号的,则通过重复添加或转换该值 减去一个可以在新类型中表示的最大值 直到该值在新类型的范围内。 (规则描述了数学值的算术,而不是给定类型表达式的值。)
否则,新类型已签名且值无法在其中表示;无论是 结果是实现定义的或引发实现定义的信号。
因此,在a>b
(a
为int
且b
为unsigned int
)中,根据上述规则,您获得{{1}在比较之前转换为a
。由于unsigned int
为负(-2),因此无符号值变为a
(这是UINT_MAX+1+a
位)。在您的情况下,repeatedly adding or
subtracting one more than the maximum value
是UINT_MAX+1+a
= UINT_MAX+1-2
,与UINT_MAX-1
(2)的值相比,这是一个巨大的正数。所以b
会产生“真实”。
忘掉你在学校学到的数学知识。了解C是如何做到的。
答案 4 :(得分:-2)
在第一种情况下,您将unsigned转换为signed int。然后将这两者进行比较。
有符号和无符号类型之间的类型转换等级在C99中可以具有相同的等级。这是无符号和有符号类型具有相应类型的情况,当发生这种情况时,结果取决于编译器。