为什么C ++将带符号的int转换为表达式中的unsigned int?

时间:2015-01-27 21:13:33

标签: c++ types casting

intunsigned int进行比较时,例如:

signed int si = -1;
unsigned int ui = 0;

if (ui > si)
{
    // Do something
}

si将转换为unsigned int,因此会大于ui。那么,如果结果不符合预期,为什么甚至允许这样做,是否因为历史原因这样做了,如果他们不得不再次这样做,他们就不会允许它?

4 个答案:

答案 0 :(得分:5)

C ++有以下规则来决定在完成整数提升后转换两个值的类型(第5章第9节):

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

最后一条规则适用于此,因为intunsigned int具有相同的排名。

答案 1 :(得分:2)

存在此规则是因为它是解决问题的最佳方法。

你无法比较苹果和橘子。唯一的选择是:

  • 将橙色转换为苹果
  • 将苹果转换为橙色
  • 将两者转换为其他常见类型

在前两个选项中,将两者都转换为无符号比将两者转换为签名更有意义。

第三种选择怎么样?我想有可能将两个值都转换为long,然后进行比较。一开始这似乎是一个好主意,但如果你再考虑一下,那么就会出现一些问题:

  • 如果longint大小相同,那么这实际上并没有帮助
  • 即使long大于int,您刚刚将问题移至将longunsigned long进行比较的情况。
  • 编写可移植代码会更难。

最后一点很重要。当您使用重载函数编写模板代码或代码时,将shortchar提升为int的历史规则实际上非常烦人,因为它会更改调用哪个重载。

我们不想再引入相同类型的规则(例如,如果与int进行比较,则将long提升为unsigned int,但仅限于sizeof(long)&gt ; sizeof(int) yada yada yada)。

答案 2 :(得分:1)

原因主要是历史性的。即使在今天,C ++仍然很容易与C代码兼容。您可以使用C代码库并将其逐字转换为C ++,它可能会起作用,即使存在一些细微差别和不兼容性。 C以这种方式定义它并且C ++不会改变它,否则它会改变代码的含义,从而破坏原本可以工作的程序。

current working draft (N4296)中,您可以找到5.10.5节中的规则。

答案 3 :(得分:0)

该语言只有两种选择:

  • 将签名视为未签名
  • 将unsigned视为已签名

正如dasblinkenlight所说,语言要求前者。原因是它使代码更简单。在现代机器中,最高位是符号位,硬件可以执行有符号或无符号比较,因此代码只是比较后跟无符号条件跳转。

要将unsigned视为signed,编译器可以丢弃(屏蔽掉)无符号字ui中的顶部位,然后执行带符号测试,但这会改变其值。或者,它可以首先测试ui的最高位,如果设置则返回更大的位,然后执行上面的屏蔽。

最重要的是,选择语言是因为它的代码效率更高。