2011-05-28 85 views
3

可能重复:
unsigned int and signed char comparison关于产品在C unsigned int类型

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是否签署。

那么它是如何工作的?

UPDATE

任何人都可以在装配水平解释一下吗?

+1

OP的问题与建议的重复不同。请不要关闭。 – 2011-05-28 16:03:51

+2

这不应该被关闭。这个问题是关于x86汇编程序。 – 2011-06-01 01:06:11

回答

4

在以下代码:

if(i > -1) 
    printf("3\n"); 
else 
    printf("4\n"); 

-1被转换为一个无符号的int,它是最大的无符号整型并清楚地大于10。

在我的机器下面的代码

#include <stdio.h> 
int main() 
{ 
    unsigned int i = -1; 
    printf("%u\n", i); 
    return 0; 
} 

收率:4294967295

+1

要扩展一点,当发生有符号/无符号比较时,两种类型总是转换为无符号。当这种转换发生时,位表示不会改变。虽然在C++标准中没有规定,但最常见的有符号整数表示是二进制补码,它基本上隐式地从无符号位表示中减去最大可能无符号值的一半。如果启用它们,编译器应该警告你。 – 2011-05-28 14:21:53

+1

这个问题被标记为C.'std :: cout',''不是C. – 2011-05-28 14:25:12

+0

@Prasoon:它只是为了说明当-1被转换为无符号值时发生了什么。改为纯粹​​的C :) – ralphtheninja 2011-05-28 14:31:01

2

当比较无符号(即i)与带符号(即-1)编译器将有符号值转换为无符号。

-1转换为无符号会给出非常大的值,因此(i > -1)条件会产生错误。

[6.3.1.3/2](C99)

否则,如果新类型是无符号的,所述值是通过反复增加或减去 比能够在表示最大值多一个转换直到新的类型 ,直到值在新类型的范围内。

4

正如其他答案所说,-1被转换为无符号整型。检查后面的跳转指令。一个应该是“ja”,另一个是“jg”:无符号和带符号的跳转指令。

+0

你能详细说一下'ja'和'jg'的东西吗? – kern 2011-05-28 15:01:45

+0

+1这是解决OP关于asm的真正问题的唯一答案,以及OP忽略了重要指令的事实:跳转。 – 2011-05-28 15:46:05

+0

'ja'与'jnc'相同 - 如果进位标志清零,则跳转。 'jg'取决于进位,符号和/或溢出标志(我忘记了详细信息,但可以自己查看或者自己完成)来实现比较复杂的签名比较。 – 2011-05-28 16:02:33

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"); } 

第一个比较有符号整数的比较。第二个是无符号整数的比较。

关于你的问题的另一个方面,汇编中确实只有一个比较指令,但它设置了各种标志。你测试你感兴趣的标志,你正在做的比较(签名,未签名,...)。

0

在可以评估“>”运算符之前,两边的操作数需要(概念上)转换为相同的类型。在这种情况下(不确定它是否是“标准”,或只是编译器的奇想)-1将被转换为无符号。 -1当然是0xFFFFFFFF,并且在无符号比较中比0x0000000A更大,尽管在有符号比较中比较小(因为高位是符号位,并且带符号的负数几乎总是以“二进制补码“)。

“底层”我怀疑在你的CPU上产生的条件代码有签名和无符号部分,两者结果的区别在于如何检查条件代码,而不是比较本身。

+0

这就是为什么明确地将数字转换为所需形式做比较,而不是依靠隐式转换。很难记住所有隐式转换规则并预测它们将如何应用。 – 2011-05-28 14:19:14

1

As @Neil G指出,虽然cmp不知道unsigned vs signed,但是条件跳转指令可以。

这样做是因为正常的算术指令(如sub)会影响所有相关的条件代码,因此您可以直接执行条件跳转,而无需进行任何明确的比较。

请注意,cmp只是一个sub,不影响目的地。