unsigned和int-gotcha

unsigned和int-gotcha,c,types,type-conversion,C,Types,Type Conversion,可能重复: 输出:a>b int b=2; int a=-2; if(a>b) printf("a>b"); else printf("b>a"); 输出:b>a 请有人解释一下输出在第一种情况下,两个操作数都转换为无符号整数,转换后的a将是UINT\u MAX-1,这比b大得多,因此输出 除非您理解算术转换的语义,否则不要比较有符号整数和无符号整数,结果可能会让您感到惊讶 以下内容摘自C编程语言的Kernighan和Ritchie-2.7类型转换-第44

可能重复:

输出:a>b

int b=2;
int a=-2;

if(a>b)
    printf("a>b");
else
    printf("b>a");
输出:b>a


请有人解释一下输出

在第一种情况下,两个操作数都转换为无符号整数,转换后的
a
将是
UINT\u MAX-1
,这比
b
大得多,因此输出


除非您理解算术转换的语义,否则不要比较有符号整数和无符号整数,结果可能会让您感到惊讶

以下内容摘自C编程语言
Kernighan
Ritchie
-
2.7类型转换
-第44页;本页的后半部分详细解释了相同的场景。下面有一小部分供您参考


当涉及
无符号
操作数时,转换规则很复杂。问题是有符号值和无符号值之间的比较依赖于机器,因为它们取决于各种
整数类型的大小。例如,假设
int
的长度为16位,
long
的长度为32位。然后,
-1L<1U
,因为
1U
,它是一个
int
,被提升为一个
带符号的long
。但是
-1L>1UL
,因为
-1L
被提升为
无符号long
,因此看起来是一个更大的正数。

在第一种情况下,将无符号a转换为有符号int。然后比较这两个值

有符号和无符号类型之间的类型转换列组在C99中可以具有相同的列组。这是当一个无符号类型和一个有符号类型具有相应的类型时,当发生这种情况时,结果由编译器决定


比较有符号值和无符号值时,如果无符号值不能全部用有符号类型表示,则有符号操作数将升级为无符号操作数。这是通过一个相当于重新解释2-s补码位模式的公式完成的

负数有很多高位

由于您的操作数都是相同的秩,所以只需比较无符号位模式即可


因此-2用111111..110表示,比可能的最大值小一个,当解释为无符号时,它很容易超过2。

您需要学习C中运算符的操作以及C升级和转换规则。它们在C标准中进行了解释。其中的一些摘录以及我的评论:

6.5.8关系运算符
语法
1关系表达式:
移位表达式
关系表达式<移位表达式
关系表达式>移位表达式
关系表达式=移位表达式

语义
3如果两个操作数都具有算术类型,则通常的算术转换为 已执行。

大多数运算符在实际操作(加法、乘法、比较等)之前都包含此“常用算术转换”步骤。-Alex

6.3.1.8常用算术转换

1许多期望算术类型的操作数的运算符会导致转换并产生结果 以类似的方式输入。目的是确定操作数的通用实数类型 结果呢。对于指定的操作数,将转换每个操作数,而不更改类型 域,指向其对应实类型为公共实类型的类型。除非 否则,公共实数类型也是 结果,其类型域是操作数的类型域(如果操作数相同), 否则会很复杂。这种模式称为通常的算术转换:

  • 首先,如果其中一个操作数的对应实数类型为长双精度,则另一个操作数 操作数在不更改域类型的情况下转换为 对应的实数类型为长双精度

  • 否则,如果任一操作数的对应实数类型为双精度,则另一个操作数 操作数在不更改域类型的情况下转换为 对应的实数类型是double

  • 否则,如果其中一个操作数的对应实数类型为float,则另一个操作数 操作数在不更改域类型的情况下转换为 相应的实数类型是float

  • 否则,将对两个操作数执行整数提升。然后 以下规则应用于提升的操作数:

  • 如果两个操作数的类型相同,则无需进一步转换

  • 否则,如果两个操作数都具有有符号整数类型或都具有无符号整数类型 整数类型,则类型为较小整数转换秩的操作数为 已转换为具有更高秩的操作数类型

  • 否则,如果具有无符号整数类型的操作数的秩大于或等于 等于另一个操作数类型的秩,然后为 有符号整数类型转换为无符号的操作数类型 整数类型

  • 否则,如果带符号整数类型的操作数的类型可以表示 具有无符号整数类型的操作数类型的所有值,然后 无符号整数类型的操作数转换为 带符号整数类型的操作数

  • 否则,两个操作数都将转换为无符号整数类型 对应于带符号整数类型的操作数的类型

6.3.1.3有符号和无符号整数

  • 当整数类型的值转换为除_Bool以外的其他整数类型时,如果该值可以用新类型表示,则该值不变

  • 否则,如果新类型是无符号的,则通过重复添加或 比新类型中可以表示的最大值多减去一个 直到值在
    int b=2;
    int a=-2;
    
    if(a>b)
        printf("a>b");
    else
        printf("b>a");