为什么比较signed char和unsigned int不能正常工作?

912*_*34K 1 c

我写了一小段代码来测试一些东西:

#include <stdio.h>

int main()
{
    unsigned  x = 1;
    signed char y = -1 ;
    if (x>y)
        printf("X > Y");
    else
        printf("X <= Y");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出是"X <= Y".不是1> -1?

oua*_*uah 10

我们有:

unsigned  x = 1;
signed char y = -1;
Run Code Online (Sandbox Code Playgroud)

这个表达式:

x > y
Run Code Online (Sandbox Code Playgroud)

用作if语句的控制表达式.

在通常的算术转换之后,右操作数y将转换为unsigned int值.负的转换结果signed char-1将是一个巨大unsigned int的值(等于UINT_MAX).

因此表达式x > y将被评估为:

1U > UINT_MAX
Run Code Online (Sandbox Code Playgroud)

这总是假的(即评估为0).

这是简短版本.为了解释我们如何使用C标准规则得出这个结果,我将在下面解释它.

这是怎么回事:

使用>关系运算符,这里是C对关系运算符的说法:

关系运算符(C99,6.5.8p3)"如果两个操作数都具有算术类型,则执行通常的算术转换."

好的,在我们的示例中,两个操作数都是整数类型,整数类型是算术类型.因此通常会进行算术转换.通常的算术转换是什么?

通常的算术转换(C99,6.3.1.8p1)"否则,对两个操作数执行整数提升.然后将以下规则应用于提升的操作数:

好的,首先对每个操作数进行整数提升.整数促销如何执行?

整数提升(C99,6.3.1.1p2)"如果int可以表示原始类型的所有值,则该值将转换为int;否则,它将转换为unsigned int.这些称为整数提升."

ysigned char类型所以它首先被提升为int整数提升后xunsigned int类型并保持一个unsigned int.

然后通常的算术转换将在两个操作数之间找到共同的类型.在我们的例子中,它意味着:

通常的算术转换(套件)(C99,6.3.1.8p1)"否则,两个操作数都转换为无符号整数类型,对应于带有符号整数类型的操作数的类型."

unsigned int具有与int类型相同的转换排名(记得signed char被提升为int),因此促销y将从int(促销后)转换为unsigned int.有关信息,整数转换等级在(C99,6.3.1.1p1)中定义.你可以注意到,在通常的算术转换中unsigned int获胜int,另一种说法是说它unsigned.

现在int,-1(signed char -1升级后int)的unsigned int值如何转换为值?`.以下是C在这种特定情况下对整数转换的说法:

整数转换(C99,6.3.1.3p2)"否则,如果新类型是无符号的,则通过重复加或减一个可以在新类型中表示的最大值来转换该值,直到该值在该范围内新类型."

编写本段以使其含义与签名的数字表示无关.对于二进制补码表示,它表示将int-1转换(UINT_MAX + 1) - 1为等于UINT_MAX.所以在我们的具体案例中,

x > y
Run Code Online (Sandbox Code Playgroud)

相当于

1U > UINT_MAX
Run Code Online (Sandbox Code Playgroud)

相当于

0
Run Code Online (Sandbox Code Playgroud)


Aln*_*tak 7

如果比较不同类型的变量,则在完成比较之前,必须将其中一个变量强制转换为另一个类型.

"较短"类型将被提升为"更长"类型.

在这种情况下,signed char y将已转换为unsigned intwith值UINT_MAX.

具体来说,假设使用32位的编译器ints:

   signed char          -1 = 0xff        becomes
-> signed int           -1 = 0xffffffff  becomes
-> unsigned int 0xffffffff = UINT_MAX
Run Code Online (Sandbox Code Playgroud)

因此x < y.