[英]Why does C++ converts a signed int to an unsigned int in an expression?
将int
与unsigned int
进行比较时,例如:
signed int si = -1;
unsigned int ui = 0;
if (ui > si)
{
// Do something
}
si
将被转换为unsigned int
,因此它将大于ui
。 那么,如果结果不符合预期,为什么甚至允许这样做,是否由于历史原因这样做,如果他们不得不再次这样做,他们就不会允许它?
C ++有以下规则来决定在完成整数提升后转换两个值的类型(第5章第9节):
- 如果两个操作数具有相同的类型,则不需要进一步转换。
- 否则,如果两个操作数都有有符号整数类型或两者都有无符号整数类型,则具有较小整数转换等级类型的操作数应转换为具有较大等级的操作数的类型。
- 否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则具有有符号整数类型的操作数应转换为具有无符号整数类型的操作数的类型。
- 否则,如果具有有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数应转换为具有有符号整数类型的操作数的类型。
- 否则,两个操作数都应转换为与带符号整数类型的操作数类型相对应的无符号整数类型。
最后一条规则适用于此,因为int
和unsigned int
具有相同的排名。
存在此规则是因为它是解决问题的最佳方法。
你无法比较苹果和橘子。 唯一的选择是:
在前两个选项中,将两者都转换为无符号比将两者都转换为有符号更有意义。
第三种选择怎么样? 我想有可能将两个值都转换为long
然后进行比较。 一开始这似乎是一个好主意,但如果你再考虑一下,那么就会出现一些问题:
long
和int
的大小相同,那么这实际上并没有帮助 long
大于int
,你也只是将问题转移到比较long
和unsigned long
。 最后一点很重要。 当您使用重载函数编写模板代码或代码时,关于short
和char
被提升为int
的历史规则实际上非常烦人,因为它会更改调用哪个重载。
我们不想再引入相同类型的规则(例如,如果它与unsigned int
相比,则将int
提升为long
,但仅限于sizeof(long)
> sizeof(int)
yada yada yada)。
原因主要是历史性的。 即使在今天,C ++仍然很容易与C代码兼容。 您可以使用C代码库并将其逐字转换为C ++,它可能会起作用,即使存在一些细微差别和不兼容性。 C以这种方式定义它并且C ++不会改变它,否则它会改变代码的含义,从而破坏原本可以工作的程序。
在当前的工作草案(N4296)中,您可以在5.10.5节中找到规则。
该语言只有两种选择:
正如dasblinkenlight所说,语言要求前者。 原因是它使代码更简单。 在现代机器中,最高位是符号位,硬件可以执行有符号或无符号比较,因此代码只是比较后跟无符号条件跳转。
要将unsigned视为signed,处理器可以丢弃(屏蔽掉)无符号字ui中的顶部位,然后执行带符号测试,但这会改变其值。 或者,它可以首先测试ui的最高位,如果设置则返回更大,然后执行上面的屏蔽。
最重要的是,语言选择是因为它更具代码效率。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.