54

请参阅此代码段

int main()
{ 
 unsigned int a = 1000;
 int b = -1;
 if (a>b) printf("A is BIG! %d\n", a-b);
 else printf("a is SMALL! %d\n", a-b); 
 return 0;
}   

这给出了输出: a is SMALL: 1001

我不明白这里发生了什么。> 运算符在这里如何工作?为什么“a”小于“b”?如果它确实更小,为什么我会得到一个正数(1001)作为差异?

4

7 回答 7

63

不同整数类型之间的二元运算在由所谓的常用算术转换定义的“通用”类型内执行(参见语言规范,6.3.1.8)。在您的情况下,“常见”类型是unsigned int. 这意味着int操作数(您的b)将unsigned int在比较之前转换为,以及为了执行减法。

-1转换为unsigned int结果时是最大可能unsigned int值(与 相同UINT_MAX)。不用说,它将大于您的无符号1000值,这意味着这a > b确实是错误a并且与(unsigned) b. 您的if代码中的 应该解析为else分支,这是您在实验中观察到的。

相同的转换规则适用于减法。你a-b真的被解释为a - (unsigned) b,结果有 type unsigned int。这样的值不能用%d格式说明符打印,因为%d只适用于带符号的值。您尝试打印它会%d导致未定义的行为,因此从 C 语言的角度来看,您看到的打印值(即使它在实践中具有逻辑确定性解释)完全没有意义。

编辑:实际上,我对未定义的行为部分可能是错误的。根据 C 语言规范,相应有符号和无符号整数类型范围的公共部分应具有相同的表示形式(根据脚注 31,这意味着“作为函数参数的可互换性”)。因此,如上所述,a - b表达式的结果是无符号的,除非我遗漏了什么,否则使用说明符打印这个特定的无符号值是合法的,因为它属于. 打印将是未定义的,但很好。1001%dint(unsigned) INT_MAX + 1%d1001u

于 2010-01-18T09:37:48.047 回答
15

int32 位的典型实现中,-1 转换unsigned int为 4,294,967,295 确实≥ 1000。

即使你在一个unsigned世界中处理减法,1000 - (4,294,967,295) = -4,294,966,295 = 1,001这就是你得到的。

这就是为什么当您与 比较时gcc会发出警告。(如果您没有看到警告,请传递标志。)unsignedsigned-Wsign-compare

于 2010-01-18T09:25:10.433 回答
1
 #include<stdio.h>
 int main()
 {
   int a = 1000;
   signed int b = -1, c = -2;
   printf("%d",(unsigned int)b);
   printf("%d\n",(unsigned int)c);
   printf("%d\n",(unsigned int)a);

   if(1000>-1){
      printf("\ntrue");
   }
   else 
     printf("\nfalse");
     return 0;
 }

为此,您需要了解运算符的优先级

  1. 关系运算符从左到右工作......所以当它出现时

    如果(1000>-1)

然后首先它将 -1 更改为无符号整数,因为 int 默认情况下被视为无符号数,并且它的范围大于有符号数

-1 会变成无符号数,变成一个很大的数

于 2018-09-12T12:30:55.537 回答
0

您正在进行无符号比较,即将 1000 与 2^32 - 1 进行比较。

由于 printf 中的 %d,输出已签名。

注意有时混合有符号和无符号操作数时的行为是特定于编译器的。我认为最好避免使用它们并在有疑问时进行强制转换。

于 2010-01-18T09:23:19.513 回答
0

找到一种简单的比较方法,当您无法摆脱无符号声明时(例如,[NSArray count])可能有用,只需将“无符号整数”强制为“整数”。

如果我错了,请纠正我。

if (((int)a)>b) {
    ....
}
于 2012-04-02T13:07:29.547 回答
0

硬件旨在比较有符号与有符号以及无符号与无符号。

如果您想要算术结果,请先将无符号值转换为更大的有符号类型。否则,编译器将假定比较实际上是在无符号值之间进行的。

而-1 表示为 1111..1111,所以它是一个非常大的数量......最大的......当解释为无符号时。

于 2012-04-20T05:26:17.807 回答
-1

在比较 a>b 时,其中 a 是 unsigned int 类型,b 是 int 类型,b 是强制转换为 unsigned int 的类型,因此,有符号 int 值 -1 被转换为 unsigned ** 的 MAX 值(范围:0 到(2^32) -1 )** 因此,a>b 即 (1000>4294967296) 变为假。因此 else loop printf("a is SMALL! %d\n", ab); 执行。

于 2018-07-09T22:36:27.670 回答