这似乎很简单,但我可能漏掉了什么,或者…没有办法做到?
第一次尝试:
unsigned abs(int value) { return value < 0 ? -value : value; }
不行,"-value"是未定义行为。这会被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
函数? - Thomas Matthewsunsigned abs(int value) { return value < 0 ? 0-value : value; }
- Alex Lop.INT_MIN
是一个边界情况,您可以直接明确处理它。这使得您可以清楚地处理该边界情况。 - chris-value
是因为在无限精度数学中,-INT_MIN比INT_MAX更大(因此会导致未定义行为)。但是在这种情况下,你希望abs(INT_MIN)
的结果是什么?在我看来,你应该选择第一种选项并接受abs(INT_MIN)
是未定义行为,或者你应该抛出某种异常。 - Chris Beck