关于C#:比较运算符如何在溢出的情况下工作

 2021-04-27 

how does comparison operator works in case of overflow

我有以下代码:

1
2
3
4
5
6
7
8
9
10
11
int main() {
   int64_t val1 = 0x8000000000000000;
   int64_t val2 = 0x1c11223344556677;
   if(val1 > val2) {
      std::cout <<"Val1 is greater than val2"<< std::endl;
   }
   else {
      std::cout <<"Val2 is greater than val1"<< std::endl;
   }
   return 0;
}

获取代码其他部分的打印内容。

我想知道在值之一超过最大值的情况下,比较运算符或与此有关的任何算术运算如何工作?


0x8000000000000000是一个大的无符号整数,十进制为9223372036854775808.

可以存储在以INT_64_MAX或类似形式表示的64位带符号整数中的最大值是9223372036854775807。

n3797 S4.7 / 3的标准中涵盖了该值从无符号到有符号的转换:

If the destination type is signed, the value is unchanged if it can be represented in the destination type (and bit-field width); otherwise, the value is implementation-defined.

由于无法如此表示,因此行为是实现定义的。

在大多数实现中实际上将发生的是,该位值将保持不变。现在val1的值超出了允许范围,使用它会导致未定义的行为。

尤其不能可靠地预测两个有符号整数之间的比较,其中一个整数超出允许范围。它可能会遵循底层机器硬件中的特定指令,因此您将必须检查生成的代码以确定将要执行的代码。我可以编写代码并告诉您所找到的内容,但是对于不同的编译器或不同的处理器,它可能有所不同。

最佳建议始终是尽可能避免未定义行为。


根据C 11§5:

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.


否则我希望您的意思是大于或等于。

Opertor根本不起作用,因为int64_t用于将值存储在limit(-2 ^ 63到2 ^ 63-1)中。如果您想要更多范围,请使用无符号版本。要获得更多范围,请使用一些随时可用的bignum库或自己编写一个。 (例如,您可以将大量数字存储在字符串中,并且比较会变得非常容易)


比较运算符照常工作:在这种情况下,val1将为负(最高有效位已设置!),因此将小于val2,即正数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

int main() {
   int64_t val1 = 0x8000000000000000;
   int64_t val2 = 0x1c11223344556677;
   std::cout <<"val1:" << val1 << std::endl;
   std::cout <<"val2:" << val2 << std::endl;
   if(val1 > val2) {
      std::cout <<"Val1 is greater than val2"<< std::endl;
   }
   else {
      std::cout <<"Val2 is greater than val1"<< std::endl;
   }
   return 0;
}

输出(ideone):

1
2
3
val1: -9223372036854775808
val2: 2022435311251187319
Val2 is greater than val1