为什么C++在表达式中将有符号的 int 转换为无符号的 int
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
的历史规则实际上非常烦人,因为它会更改调用的重载。
我们不想再引入任何相同类型的规则(例如,如果int
与unsigned int
相比,则将其提升为long
,但前提是sizeof(long)
> sizeof(int)
yada yada yada)。
原因主要是历史原因。即使在今天,C++与 C 代码兼容也很重要。你可以采用一个 C 代码库并将其逐字转换为 C++ 它可能会起作用,即使存在一些细微的差异和不兼容性。C 以这种方式定义它,C++不会更改它,否则它会改变代码的含义,从而破坏本来可以工作的程序。
在当前的工作草案(N4296)中,您可以在第5.10.5节中找到规则。
该语言只有两种选择:
- 将已签名视为未签名
- 将未签名视为已签名
正如达斯布林肯莱特所说,语言要求前者。原因是它使代码更简单。在现代机器中,顶部位是符号位,硬件可以执行有符号或无符号比较,因此代码只是一个比较,然后是无符号条件跳转。
若要将未签名视为已签名,编译器可以丢弃(屏蔽)无符号单词 UI 中的顶部位,然后执行已签名测试,但这会更改其值。或者,它可以先测试 ui 的顶部位,如果设置,则返回更大的内容,然后执行上述掩码。
最重要的是,选择语言是因为它的代码效率更高。
- 是否可以从int转换为enum类类型
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 是什么导致了这种使用三进制而不是短整型的有符号int到无符号int转换
- 将字符串中的 int 转换为字母;
- 主.cpp:18:20:错误:从"int*"转换为"int"会失去精度 [-fa
- 将非常大的 int 转换为双倍,在某些计算机上会损失精度
- 如何将矢量<int>转换为字符数组?
- C++ 无法从 const int* 转换为 const_iterator
- 我不断收到错误 C2440'=':无法从"int *(__cdecl *)(int *,int *,int,int)"转换为"int *
- 如何将 int[4] 转换为 std::array<int,4>?
- 如何将data[i].int转换为vaible
- 将 int 转换为字符串,然后连接另一个变量以创建完整扩展名,然后将其转换为 const_char*
- 将私有矩阵形式 int 转换为双 C++
- 无法将参数 1 从 'int' 转换为 'int &'
- 将 int 转换为字符串后始终得到 0
- isspace 函数的性能警告,从 int 转换为布尔值
- 将大 int 转换为浮点数,而不舍入 c++
- 错误:无法将'uint8* {aka unsigned int*}'转换为"常量emxArray_uint8_T*"?
- 将未签名的INT转换为BCD
- 在 C++ 中将 int 转换为双精度