算术运算中的数据类型提升:-1 < (无符号整数) 1 == 假

11
main()  {   
  if ( -1 < (unsigned char) 1 )
    printf("less than");
  else        
    printf("NOT less than");
} 
打印“less than”。因为(unsigned char) 1被转换为(signed char) 1,然后:(signed) -1 < (signed) 1,因此输出为less than。但是,如果我将上面的代码更改为if ( (-1 < (unsigned int) 1 ),那么输出结果就是NOT less than。因此很明显,当我将unsigned char更改为unsigned int时:(signed) -1被转换为unsigned int [正好相反],由于-1存储为1的2's补码;比特模式被评估为255(可能),因此255 < 1将计算为false并执行else语句。即使你在'-1'的位置上替换int a = -1;也会得到同样的结果。
问题: 1.在有符号和无符号算术中...如何确定有符号值将被转换为无符号值还是反之? 2.为什么unsigned char和char之间的转换与unsigned int和int之间的转换不同:显然,unsigned被转换为signed,并且signed int和int:显然,signed被转换为unsigned。
PS:我知道这不是编译器相关的..所以不要说它是。

所有文字量都是标准整数吗?(无符号字符->整数升级与整数->无符号整数升级) - flownt
2个回答

10
以下是规则:

6.3.1.8常规算术转换

...

否则,对两个操作数执行整数提升。然后将以下规则应用于提升的操作数:

  1. 如果两个操作数具有相同的类型,则不需要进一步转换。
  2. 否则,如果两个操作数都具有带符号整数类型或都具有无符号整数类型,则类型等级较低的操作数被转换为具有更高等级的操作数的类型。
  3. 否则,如果具有无符号整数类型的操作数的等级大于或等于另一个操作数的类型的等级,则具有带符号整数类型的操作数会被转换为具有无符号整数类型的操作数的类型。
  4. 否则,如果具有带符号整数类型的操作数的类型可以表示无符号整数类型的所有值,则具有无符号整数类型的操作数将被转换为具有带符号整数类型的操作数的类型。
  5. 否则,两个操作数都将转换为与具有带符号整数类型的操作数的类型相对应的无符号整数类型。

然后规则工作如下:

  • -1 < (unsigned char) 1

首先,两个操作数都转换为int(因为int可以表示unsigned char的所有值)。然后使用有符号类型进行比较。接着使用规则1。比较成功。

  • -1 < (unsigned int) 1

int无法表示unsigned int的所有值,所以使用规则3,将带符号整数转换为无符号整数(UINT_MAX - 1)。现在比较失败。


1
"rank"是什么意思?它意味着什么? - bakra
@bakra:你可以把它看作是类型的“排序”。例如,long int 的等级比 char 高。请参阅6.3.1.1以获取等级的官方定义。 - Mark Byers
1
@bakra:“rank”是在C标准的其他地方定义的,但其要点是哪种类型具有更大范围的可能值,还有一些例外情况。特别是,“有符号整数类型的等级应大于具有较低精度的任何有符号整数类型的等级。”和“如果有的话,任何无符号整数类型的等级应等于相应有符号整数类型的等级。” - aschepler
在评估这些编号的子弹之前,每种比“int”低的类型都会转换为“int”或者如果“int”不能存储其值,则转换为“unsigned int”。因此,在评估所有这些编号的子弹之前,两个操作数已经是“int”类型,而选择第一个子弹。就像@ninjalj所说的那样。 - Johannes Schaub - litb
UINT_MAX - 1,而不是INT_MAX - 1。 - Stephen Canon
显示剩余2条评论

1
这是由于整数提升导致的。两个参数都可以表示为int,因此它们被转换为int。
ISO C 6.3.1.1第2段:

如果int可以表示原始类型的所有值,则将其转换为int;否则,将其转换为无符号int。这些称为整数晋升。48)所有其他类型都不受整数晋升的影响。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接