int j = 10;
unsigned int i = 10;
if( j > -1 )
printf("1\n");
else
printf("2\n");
if( i > -1 )
printf("3\n");
else
printf("4\n");
输出结果为:
1
4
我已经进入了集会,比较是相似的:
cmp dword ptr [ebp-10h],0FFFFFFFFh
...
cmp dword ptr [ebp-14h],0FFFFFFFFh
但仍然不明白为什么一个是真的而另一个是假的。
IMO cpu不知道dword ptr
是否已签名。
那么它是如何在引擎盖下工作的?
更新
任何人都可以在汇编级别解释它吗?
答案 0 :(得分:4)
在以下代码中:
if( i > -1 )
printf("3\n");
else
printf("4\n");
-1被转换为unsigned int,这是最大的unsigned int,显然大于10。
在我的机器上使用以下代码
#include <stdio.h>
int main()
{
unsigned int i = -1;
printf("%u\n", i);
return 0;
}
收益率:4294967295
答案 1 :(得分:4)
正如其他答案所说,-1正在转换为unsigned int。检查以下跳转说明。一个应该是“ja”而另一个应该是“jg”:未签名和签名的跳转指令。
答案 2 :(得分:2)
当比较无符号(即i
)和带符号(即-1)时,编译器将有符号值转换为无符号值。
将-1
转换为无符号会产生非常大的值,因此( i > -1)
条件会产生错误。
[6.3.1.3/2](C99)
否则,如果新类型是无符号的,则通过重复添加或转换该值 减去一个可以在新类型中表示的最大值 直到该值在新类型的范围内。
答案 3 :(得分:1)
这是你的程序注释它包含的所有隐式转换:
int j;
unsigned int i;
j = 10;
i = (unsigned int)10;
if (j > -1) { printf("1\n"); }
else { printf("2\n"); }
if (i > (unsigned int)-1) { printf("3\n"); }
else { printf("4\n"); }
第一个比较是签名的整数比较。第二个是无符号整数的比较。
关于你问题的另一个方面,汇编中确实只有一个比较指令,但它设置了各种标志。您测试您感兴趣的标志以进行比较(已签名,未签名,......)。
答案 4 :(得分:1)
正如@Neil G指出的那样,虽然cmp
不知道unsigned vs signed,但条件跳转指令却是这样。
这是通过这种方式完成的,因为正常的算术指令(如sub
)会影响所有相关的条件代码,因此您可以直接执行条件跳转,而无需进行任何显式比较。
请注意,cmp
只是sub
,不会影响目的地。
答案 5 :(得分:0)
在“&gt;”之前可以评估运算符,双方的操作数需要(概念上)转换为相同的类型。在这种情况下(不确定它是“标准”,还是只是编译器的奇思妙想)-1将转换为无符号。 -1当然是0xFFFFFFFF,并且在无符号比较中比0x0000000A更大,但在有符号比较中它更小(因为高位是符号位,有符号的负数几乎总是表示在“二进制补码“)。
“引擎盖下”我怀疑在你的CPU上,结果条件代码有签名和无符号部分,两个结果之间的差异与条件代码的检查方式有关,而不是比较本身。 / p>
答案 6 :(得分:-1)
比较unsigned int和signed int时,signed int将转换为unsigned int。将负的signed int转换为unsigned int是通过添加UINT_MAX + 1来完成的。
因此-1转换为UINT_MAX + 1 - 1 = UINT_MAX,优于10。
另见What's the difference between the "unsigned preserving" and "value preserving" rules?