【问题标题】:Is a safe accumulator really this complicated?安全蓄能器真的这么复杂吗?
【发布时间】:2014-08-19 22:17:45
【问题描述】:

我正在尝试编写一个在输入不受约束的情况下表现良好的累加器。这似乎不是微不足道的,需要一些非常严格的计划。真的有这么难吗?

int naive_accumulator(unsigned int max,
                      unsigned int *accumulator,
                      unsigned int amount) {
    if(*accumulator + amount >= max) {
        return 1; // could overflow
    }

    *accumulator += max; // could overflow

    return 0;
}

int safe_accumulator(unsigned int max,
                     unsigned int *accumulator,
                     unsigned int amount) {
    // if amount >= max, then certainly *accumulator + amount >= max
    if(amount >= max) {
        return 1;
    }

    // based on the comparison above, max - amount is defined
    // but *accumulator + amount might not be
    if(*accumulator >= max - amount) {
        return 1;
    }

    // based on the comparison above, *accumulator + amount is defined
    // and *accumulator + amount < max
    *accumulator += amount;

    return 0;
}

编辑:我已经消除了风格偏见

【问题讨论】:

  • “复杂”版本比“简单”版本多 1 行代码(如果您对 safe 使用与 naive 相同的样式约定),这似乎并不太“难”...
  • 如果累计值和最大值之间的差值大于新值,则抛出异常(或其他)。
  • A) 为什么不通过引用而不是使用指针来传递?和 B) 为什么不使用 or (||) 并利用短路使safe_accumulatornaive_accumulator 的行数相同?
  • @Jongware:好吧,除非unsigned intunsigned long 的宽度相同。
  • @Jongware 除非 unsigned long 与 unsigned int 的大小相同。

标签: c++ c undefined-behavior integer-overflow


【解决方案1】:

您是否考虑过:

if ( max - *accumulator < amount )
    return 1;

*accumulator += amount;
return 0;

通过在“幼稚”版本中更改第一次比较的方向,您可以避免溢出,即查看剩余空间(安全)并将其与要添加的数量(也安全)进行比较。

此版本假定在调用函数时*accumulator 永远不会超过max;如果你想支持这种情况,那么你必须添加一个额外的测试。

【讨论】:

  • 我希望它支持 *accumulator 已经大于最大值的情况,这就是我在问题中指定不受约束的原因。你能告诉我支持无约束输入的版本吗? @Deduplicator 暗示我的有一个错误。
  • @Martin 在开头添加if ( *accumulator &gt; max ) { /* do whatever you want to do in this case */ }
  • @Martin “如果 max == UINT_MAX,你的额外测试将永远不会通过”——当然,这是故意的。如果max == UINT_MAX*accumulator 不能大于它。
  • " 如果 max == UINT_MAX、amount == UINT_MAX 和 *accumulator > 0,您的函数将溢出" - 不,它将返回 1
  • 我已经使用调试器逐步完成了它,你是对的。我很困惑,我已经删除了我的评论。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-12
相关资源
最近更新 更多