【问题标题】:How to implement unsigned abs(int)? [duplicate]如何实现无符号abs(int)? [复制]
【发布时间】:2015-12-17 01:02:15
【问题描述】:

所以这看起来很容易,但要么我错过了一些东西,要么......没有办法做到这一点?..

第一次尝试:

unsigned abs(int value) { return value < 0 ? -value : value; }

不,“-value”是一个 UB。这是由 clang -fsanitize 检测到的,并且在面对激进的优化时通常是不安全的(尽管我真的希望没有理智的编译器会滥用它)。

好的。让我们转换为未签名的!

unsigned abs(int value) { return value < 0 ? -unsigned(value) : unsigned(value); }

不,这会导致 MSVC 中出现 C4146 警告。此外,由于对无符号值的一元减号的定义,我认为这假定有符号整数采用二补整数格式。

好的...

unsigned abs(int value) { return value < 0 ? ~unsigned(value) + 1 : unsigned(value); }

这似乎不会产生任何警告或未定义的行为,但当然只适用于二补整数。此外,它有点晦涩 - 需要一个评论来解释为什么这不是使用简单的东西......

实际上是否可以在不触发 UB 或依赖整数表示的情况下实现上述功能?请在我对 C 失去所有希望之前告诉我答案是“是”。

【问题讨论】:

  • 您是将有符号整数转换为无符号整数还是需要一个以unsigned int 为参数的abs 函数?
  • 用 0-val 代替 -val 怎么样? unsigned abs(int value) { return value &lt; 0 ? 0-value : value; }
  • 由于INT_MIN 是一个极端情况,你可以明确地处理它。这清楚地表明您可以处理边缘情况。
  • 等等,所以你对-value 不满意,因为 -INT_MIN (在无限精度数学中)大于 INT_MAX (因此给出 UB)。但在那种情况下,你想成为 abs(INT_MIN) 的结果是什么? IMO,您应该只选择第一个选项并接受 abs(INT_MIN) 是 UB,或者您应该抛出某种异常。
  • @n.m.,不!请仔细阅读 std::abs 的问题和文档。

标签: c++ c integer-overflow


【解决方案1】:

正确的方法是 #2,但要使 MSVC 警告静音,需要应用解决方法:

unsigned abs(int value) { return value < 0 ? 0 - unsigned(value) : unsigned(value); }

这是正确的原因是有符号到无符号的转换被定义为返回 2^N+v 为负 v;无符号整数的一元减号定义为 2^N-v;因此,无论有符号整数表示如何,此代码都会正确返回绝对值。

【讨论】:

    【解决方案2】:

    如果-value 可能导致未定义的行为,那么应该明确定义:

    unsigned abs(int value) { return value < 0 ? 0-value : value; }
    

    【讨论】:

      猜你喜欢
      • 2012-07-05
      • 2013-03-11
      • 2010-10-20
      • 2020-06-07
      • 2011-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多