Ste*_*314 9 c c++ integer-overflow
编辑公共健康警告 - 此问题包含有关未定义行为的错误假设.见接受的答案.
在阅读了最近的博客文章后,我一直在思考避免C和C++代码中所有标准未定义假设的实用性.这是一个用C++剪切的片段,用于做无符号的128位加法......
void c_UInt64_Pair::operator+= (const c_UInt64_Pair &p)
{
m_Low += p.m_Low;
m_High += p.m_High;
if (m_Low < p.m_Low) m_High++;
}
Run Code Online (Sandbox Code Playgroud)
这显然依赖于关于溢出行为的假设.显然,大多数机器都可以支持正确类型的二进制整数(尽管可能是从32位块或其他任何东西构建的),但优化者可能会在这里利用标准未定义的行为.也就是说,m_Low < p.m_Low条件可以通过的唯一方法是m_Low += p.m_Low溢出,这是未定义的行为,因此优化器可以合法地确定条件总是失败.在这种情况下,这个代码就被打破了.
问题是,因此......
如何在不依赖未定义行为的情况下编写上述合理有效的版本?
假设您有一个适当的64位二进制机器整数,但您有一个恶意编译器,它将始终以最坏的(或不可能的)方式解释您的未定义行为.此外,假设您没有一些特殊的内置,内在,库或其他任何为您执行此操作的内容.
EDIT 略微澄清 - 这不仅仅是关于检测溢出,而且还确保m_Low和m_High都以正确的模2 ^ 64结果结束,这也是标准未定义的.
Dav*_*ley 15
从C++ 1998标准3.9.1(4):"无符号整数,声明无符号整数,应遵守算术模2 ^ n的定律,其中n是整数特定大小的值表示中的位数." 注意,"整数"在这里指的是任何整数类型而不仅仅是int.
因此,假设那些是无符号整数,如类型中的"UInt64"所示,这是C++中定义的行为,应该按预期工作.
| 归档时间: |
|
| 查看次数: |
1665 次 |
| 最近记录: |