Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么C++;将表达式中的有符号整数转换为无符号整数?_C++_Types_Casting - Fatal编程技术网

C++ 为什么C++;将表达式中的有符号整数转换为无符号整数?

C++ 为什么C++;将表达式中的有符号整数转换为无符号整数?,c++,types,casting,C++,Types,Casting,比较int与无符号int时,例如: signed int si = -1; unsigned int ui = 0; if (ui > si) { // Do something } si将转换为无符号int,因此它将大于ui。那么,如果结果不符合预期,为什么还要这样做呢?这样做是出于历史原因吗?如果他们不得不再次这样做,他们也不会允许这样做?C++有以下规则来决定在整数升级完成后将两个值转换为哪种类型(第5章,第9条): 如果两个操作数的类型相同,则无需进一步转换 否则,如

比较
int
无符号int
时,例如:

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

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

si
将转换为
无符号int
,因此它将大于
ui
。那么,如果结果不符合预期,为什么还要这样做呢?这样做是出于历史原因吗?如果他们不得不再次这样做,他们也不会允许这样做?

C++有以下规则来决定在整数升级完成后将两个值转换为哪种类型(第5章,第9条):

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

最后一条规则适用于这里,因为
int
unsigned int
具有相同的等级。

原因主要是历史原因。即使在今天,C++也与C代码兼容。您可以采用C代码库,并逐字转换为C++,即使有一些小的差异和不兼容,它也可能会工作。C已经定义了这种方式,C++将不会改变它,因为否则它会改变代码的含义,从而破坏否则会工作的程序。p>
在中,您可以找到第5.10.5节中的规则。

此规则之所以存在,是因为它是问题的最佳解决方案

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

  • 把橘子换成苹果
  • 把苹果换成橙色
  • 将两者转换为其他常见类型
在前两个选项中,将两者转换为unsigned比将两者转换为signed更有意义

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

  • 如果
    long
    int
    的大小相同,那么这实际上没有帮助
  • 即使
    long
    大于
    int
    ,您也将问题转移到比较
    long
    无符号long
    的情况
  • 编写可移植代码将更加困难
最后一点很重要。当您编写模板代码或使用重载函数编写代码时,将
short
char
升级为
int
的历史规则实际上非常烦人,因为它会改变调用哪个重载


我们不想引入任何相同类型的规则(例如,如果与
无符号int
相比,将
int
提升为
long
,但前提是
sizeof(long)
sizeof(int)
yada-yada-yada)

该语言只有两种选择:

  • 将已签名的视为未签名的
  • 将未签名的视为已签名
正如dasblinkenlight所说,语言要求前者。原因是它使代码更简单。在现代机器中,最上面的位是符号位,硬件可以执行有符号或无符号比较,因此代码只是一个比较,然后是一个无符号条件跳转

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


归根结底,选择语言是因为它的代码效率更高。

这是不应混合使用有符号和无符号的原因之一。我只能假设默认的整数比较运算符按位比较性能,而不是按有符号/无符号值进行比较。这可能是通过这种方式进行性能推理的。我会让一个大师解释一下,因为我也感兴趣。如果C++将一个未签名的int转换成一个已签名的int,那么问题仍然会发生。e、 g.
signed int si=0;unsigned int ui=(unsigned)-1;如果(ui>si){//Do something}
请参阅to question.with
clang-Weverything
您将收到一条关于此类比较的警告。但是,如果隐式转换可能导致意外结果,为什么首先允许隐式转换,请执行其他操作(新创建的)编程语言允许这种行为?为什么将两者转换为无符号比将两者转换为有符号更有意义?@BenjaminLindley嗯,转换为有符号会调用实现定义的行为,而转换为无符号则不会。由于转换为签名实际上没有任何其他好处,相比于转换为无符号,这意味着转换为无符号是更好的。@ MaMoudjt1,这只是意外的,如果你没有从一个好的学习参考学习:)C++是强类型的;在查看任何表达式时,请记住每个子表达式的类型,并且还请记住必须在编译时知道该类型。我不是指“意外”,因为我不知道这种行为会发生