Bil*_*eal 12 c++ integer integer-overflow
考虑一个典型的绝对值函数(为了参数,最大大小的整数类型很长):
unsigned long abs(long input);
Run Code Online (Sandbox Code Playgroud)
这种天真的实现可能看起来像:
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...
}
}
Run Code Online (Sandbox Code Playgroud)
此代码触发未定义的行为,因为否定input可能溢出,并且触发有符号整数溢出是未定义的行为.例如,在2s补码机器上,绝对值std::numeric_limits<long>::min()将大于1 std::numeric_limits<long>::max().
图书馆作者可以做些什么来解决这个问题?
Bil*_*eal 19
首先可以转换为无符号变体.这提供了明确定义的行为.如果相反,代码如下所示:
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...
}
}
Run Code Online (Sandbox Code Playgroud)
我们调用两个定义良好的操作.将有符号整数转换为无符号整数由N3485 4.7 [conv.integral]/2很好地定义:
如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 ^ n,其中n是用于表示无符号类型的位数).[注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断). - 结束说明]
这基本上说,当进行从signed到unsigned的特定转换时,可以假设无符号样式的环绕.
5.3.1 [expr.unary.op]/8很好地定义了无符号整数的否定:
通过从2 ^ n减去其值来计算无符号数量的负数,其中n是提升的操作数中的位数.
这两个要求有效地迫使实现像2s补充机器一样操作,即使底层机器是1s补码或有符号幅度的机器.
| 归档时间: |
|
| 查看次数: |
2204 次 |
| 最近记录: |