我写了一小段代码来测试一些东西:
#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.这些称为整数提升."
y是signed char类型所以它首先被提升为int整数提升后x的unsigned 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)
如果比较不同类型的变量,则在完成比较之前,必须将其中一个变量强制转换为另一个类型.
"较短"类型将被提升为"更长"类型.
在这种情况下,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.