关于c中unsigned int的问题

时间:2011-05-28 14:09:39

标签: c x86 assembly unsigned

  

可能重复:
  unsigned int and signed char comparison

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

那么它是如何在引擎盖下工作的?

更新

任何人都可以在汇编级别解释它吗?

7 个答案:

答案 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?