std::numeric_limits的绝对值<long long>::min()

问题描述 投票:0回答:1

简介:

我们假设以下代码

#include <cmath>
#include <limits>

int main(int, char**)
{
    long long v = std::numeric_limits<long long>::min();
    unsigned long long av = std::abs(v);
    
    return 0;
}

这里的问题是

std::abs(v)
的返回类型是
long long
并且
std::numeric_limits<long long>::min()
的绝对值不能用
long long
表示(不确定标准是否要求,但至少对于我的平台)。我相信里面
std::abs(v)
我已经有符号整数溢出,这就是UB。

简单的解决方案应该是

unsigned long long myabs(long long v)
{
    if (v == std::numeric_limits<long long>::min())
        return static_cast<unsigned long long>(std::numeric_limits<long long>::max()) + 1;
    return static_cast<unsigned long long>(abs(v));
}

总结:

是否有更好的方法(标准或非标准)来获取

std::numeric_limits<long long>::min()
的绝对值?

在这里你可以找到一些关于C的建议,但我正在寻找C++解决方案。

c++ long-integer integer-overflow
1个回答
0
投票
template <std::signed_integral integer>
constexpr std::make_unsigned_t<integer>
uabs(integer const i){
       constexpr static auto sign
            = std::bit_cast< std::make_unsigned_t<integer>>
            ( std::numeric_limits<integer>::min() );
       auto const value
            = std::bit_cast<decltype(sign)>(i);
       return (value > sign)
            ? (static_cast<decltype(sign)>(0u) - value)
            : (value);
};

这适用于 2 的补码签名平台。对于任何有符号整数类型。

© www.soinside.com 2019 - 2024. All rights reserved.