c++ - 如何在没有未定义行为的情况下进行双 block 添加?

标签 c++ c integer-overflow

编辑 公共(public)健康警告 - 这个问题包含关于未定义行为的错误假设。查看已接受的答案。

看完之后recent blog post ,我一直在思考在 C 和 C++ 代码中避免所有标准未定义假设的实用性。这是从 C++ 中截取的片段,用于执行无符号的 128 位加法...

void c_UInt64_Pair::operator+= (const c_UInt64_Pair &p)
{
  m_Low  += p.m_Low;
  m_High += p.m_High;

  if (m_Low < p.m_Low)  m_High++;
}

这显然依赖于关于溢出行为的假设。显然,大多数机器都可以支持正确类型的二进制整数(尽管可能是从 32 位 block 或其他任何东西构建的),但显然优化器可能会在这里利用标准未定义的行为的可能性越来越大。也就是说,m_Low < p.m_Low 的唯一途径条件可以通过是 if m_Low += p.m_Low溢出,这是未定义的行为,因此优化器可以合法地决定条件总是失败。在这种情况下,这段代码就被破坏了。

问题是,因此...

如何在不依赖未定义行为的情况下编写上述代码的合理高效版本?

假设您有一个适当的 64 位二进制机器整数,但您有一个恶意编译器,它总是以最坏的可能(或不可能)的方式解释您的未定义行为。此外,假设您没有一些特殊的内置、内在、库或任何可以为您做的事情。

编辑 次要澄清 - 这不仅仅是关于检测溢出,还确保 m_Low 和 m_High 最终得到正确的模 2^64 结果,这也是标准未定义的。

最佳答案

来自 C++ 1998 标准 3.9.1(4):“无符号整数,声明为无符号,应遵守算术模 2^n 的法则,其中 n 是整数的特定大小的值表示中的位数”请注意,此处的“整数”指的是任何整数类型,而不仅仅是 int

因此,假设这些是无符号整数,如类型中的“UInt64”所暗示的那样,这是 C++ 中定义的行为并且应该按预期工作。

关于c++ - 如何在没有未定义行为的情况下进行双 block 添加?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3569424/

相关文章:

c++ - 变量在传递给共享库函数时没有相同的值

在 C 中声明 typedef 枚举的正确方法?

python - 在 Python 中模拟整数溢出

c++ - 获取/释放内存排序示例

c++ - 将 const-string 分配给常量大小的 char 数组,未使用的数组索引会发生什么?

c++ - OpenCV 解决任意系统的返回常量值?

c++ - 是否从任何被视为未定义行为的整数中减去 INT_MIN?

c++ - 如何授予Boost Pool访问GSL矩阵以执行任务的线程

c++ - 常用 C++ 优化技术列表

c - 环绕 C 中有符号和无符号变量的解释?