【问题标题】:how does comparison operator works in case of overflow溢出时比较运算符如何工作
【发布时间】:2015-07-06 17:25:24
【问题描述】:

我有以下代码:

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;
}

获取打印的 else 部分代码。

我想知道比较运算符或任何算术运算在其中一个值超过最大值的情况下如何工作?

【问题讨论】:

    标签: c++ c


    【解决方案1】:

    根据 C++11 §5:

    如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义

    【讨论】:

    • 这里没有“表达式求值”。这两个整数是通过直接给出它们的十六进制值来定义的。
    • @kol 这里,int64_t val1 = ... 是评估表达式。 :P
    【解决方案2】:

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

    可以存储在 64 位有符号整数(由 INT_64_MAX 或类似值表示)中的最大值为 9223372036854775807。

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

    如果目标类型是有符号的,如果它可以在目标类型(和位域宽度)中表示,则值不变;否则,该值是实现定义的。

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

    在大多数实现中实际发生的情况是位值将保持不变。现在 val1 的值超出了允许范围,任何使用它都会导致 Undefined Behaviour。

    尤其是两个有符号整数之间的比较,其中一个超出允许范围,无法可靠地预测。它可能会遵从底层机器硬件中的特定指令,因此您必须检查生成的代码以确定是哪条指令。我可以编写代码并告诉你我发现了什么,但是对于不同的编译器或不同的处理器,它可能会有所不同。

    最好的建议是尽可能避免未定义的行为。

    【讨论】:

    • 我认为比较没有错。在进行比较时,val1 初始化中的实现定义行为已经发生(并且已将其置于int64_t 允许范围内的值中)。所以当if (val1 &gt; val2)被执行时val1的值是实现定义的,因此扩展比较的结果也将是实现定义的。
    • @AndreKostur:(a) 标准没有定义“错误”(b) 在大多数实现中,赋值将不会将有效的有符号整数值放入 val1 (c)与超出范围值的比较是 UB。如果您愿意,可以通过从 unsigned 到 int 到 unsigned 的往返来轻松地测试 (b)。
    【解决方案3】:

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

    Operator 根本不起作用,因为 int64_t 旨在将值存储在限制(-2^63 到 2^63-1)中。如果您想要更多范围,请使用未签名版本。要获得更多范围,请使用一些现成的 bignum 库或自己编写一个。 (比如你可以store large numbers in string,对比会变得非常容易)

    【讨论】:

      【解决方案4】:

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

      #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):

      val1: -9223372036854775808
      val2: 2022435311251187319
      Val2 is greater than val1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-27
        • 1970-01-01
        • 2021-11-26
        • 1970-01-01
        • 1970-01-01
        • 2012-10-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多