考虑一个典型的绝对值函数(出于参数目的,最大大小的整数类型很长):

unsigned long abs(long input);

一个简单的实现可能看起来像这样:
unsigned long abs(long input)
{
    if (input >= 0)
    {
        // input is positive
        // We know this is safe, because the maximum positive signed
        // integer is always less than the maximum positive unsigned one
        return static_cast<unsigned long>(input);
    }
    else
    {
        return static_cast<unsigned long>(-input); // ut oh...
    }
}

此代码触发未定义的行为,因为input的取反可能会溢出,并且触发有符号整数溢出是未定义的行为。例如,在2s补码机上,std::numeric_limits<long>::min()的绝对值将比std::numeric_limits<long>::max()大1。

图书馆作者可以采取什么措施来解决此问题?

最佳答案

可以先转换为无符号变体。这提供了明确定义的行为。如果相反,代码如下所示:

unsigned long abs(long input)
{
    if (input >= 0)
    {
        // input is positive
        return static_cast<unsigned long>(input);
    }
    else
    {
        return -static_cast<unsigned long>(input); // read on...
    }
}

我们调用两个定义明确的操作。 N3485 4.7 [conv.integral]/2很好地定义了将有符号整数转换为无符号整数:



这基本上说,当进行从有符号到无符号的特定转换时,可以假定无符号样式的环绕。

无符号整数的取反由5.3.1 [expr.unary.op]/8很好地定义:



这两个要求有效地迫使实现方案像2s补码机一样操作,即使基础机器是1s补码机或有符号幅度的机也是如此。

关于c++ - 有没有一种安全的方法来获取有符号整数的无符号绝对值,而不会触发溢出?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17313579/

10-11 22:46
查看更多