c++ - 如何实现unsigned abs(int)?

标签 c++ c integer-overflow

<分区>

所以这看起来很简单,但要么我遗漏了什么,要么...没有办法做到这一点?..

第一次尝试:

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 失去所有希望之前告诉我答案是"is"。

最佳答案

正确的方法是#2,但要消除 MSVC 警告,需要应用变通方法:

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

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

关于c++ - 如何实现unsigned abs(int)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32676417/

相关文章:

C 整数关闭,可能溢出

c++ - 客户端断开连接后处理服务器应用程序中的线程

C++ 自定义调用约定

c - 将 .Glade(或 xml)文件转换为 C 源代码的工具

language-agnostic - 什么是整数溢出错误?

c# - 我如何定义一个检查整数列表

c++ - ifstream read 和 fread 不返回相同的数据,C++

c++ - C++ 20范围 View 到 vector

c - 将 uint16_t var 打印到 4 个位置的函数将不起作用

c - 如何在 C 中检索传递给 linux 系统调用的参数?