如何实现unsigned abs(int)?
How to implement unsigned abs(int)?
所以这看起来很简单,但要么我遗漏了什么,要么...没有办法做到?..
第一次尝试:
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 或不依赖整数表示的情况下实现上述功能?请告诉我答案是 "yes",以免我对 C 失去所有剩余的希望。
如果 -value
可能导致未定义的行为,那么应该明确定义:
unsigned abs(int value) { return value < 0 ? 0-value : value; }
正确的方法是 #2,但要消除 MSVC 警告,需要应用解决方法:
unsigned abs(int value) { return value < 0 ? 0 - unsigned(value) : unsigned(value); }
这是正确的原因是有符号到无符号的转换被定义为 return 2^N+v 对于负 v;无符号整数的一元减号定义为 2^N-v;因此,无论有符号整数表示如何,此代码 return 都是正确的绝对值。
所以这看起来很简单,但要么我遗漏了什么,要么...没有办法做到?..
第一次尝试:
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 或不依赖整数表示的情况下实现上述功能?请告诉我答案是 "yes",以免我对 C 失去所有剩余的希望。
如果 -value
可能导致未定义的行为,那么应该明确定义:
unsigned abs(int value) { return value < 0 ? 0-value : value; }
正确的方法是 #2,但要消除 MSVC 警告,需要应用解决方法:
unsigned abs(int value) { return value < 0 ? 0 - unsigned(value) : unsigned(value); }
这是正确的原因是有符号到无符号的转换被定义为 return 2^N+v 对于负 v;无符号整数的一元减号定义为 2^N-v;因此,无论有符号整数表示如何,此代码 return 都是正确的绝对值。