算术运算期间的数据类型提升:-1 <(unsinged int)1 == false

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被存储为2的恭维1; 位模式评估为255(可能)
  • 因此255 <1将评估为false,否则将执行。
  • 即使你用int a = -1;替换int a = -1; 代替’-1’相同的结果

问题:

  1. 在有符号和无符号算术期间…如何确定签名是否将转换为无符号或反之亦然。

  2. 为什么unsigned char和char之间的算术转换不同:显然unsigned转换为signed和unsigned int和int:显然签名转换为unsigned

PS:我知道这不依赖于编译器。所以不要说它。

规则如下:

6.3.1.8通常的算术转换

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

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

然后规则如下:

  • -1 < (unsigned char) 1

首先将两个操作数转换为整数(因为int可以表示unsigned char的所有值)。 然后对这些签名类型进行比较。 然后使用规则1。 比较成功。

  • -1 < (unsigned int) 1

int不能表示unsigned int的所有值,因此使用规则3并且有符号整数将转换为无符号整数(UINT_MAX - 1)。 比较现在失败了。

这是由于整数促销 。 两个参数都可以表示为int,因此它们将转换为int。

ISO C 6.3.1.1,第2段:

如果int可以表示原始类型的所有值,则该值将转换为int; 否则,它将转换为unsigned int。 这些被称为整数促销.48)所有其他类型由整数促销不变。