【问题标题】:What's an efficient way to avoid integer overflow converting an unsigned int to int in C++?什么是避免整数溢出在 C++ 中将 unsigned int 转换为 int 的有效方法?
【发布时间】:2011-03-02 02:45:24
【问题描述】:

以下是在 C++ 中将 unsigned int 转换为 int 的有效且无问题的方法吗:

#include <limits.h>
void safeConvert(unsigned int passed) 
{
    int variable = static_cast<int>(passed % (INT_MAX+1)); 
    ...
}

或者有更好的方法吗?

更新

正如 James McNellis 所指出的,将 unsigned int > INT_MAX 分配给整数并不是未定义的——而是由实现定义的。因此,这里的上下文现在特别是我的偏好是确保当 unsigned int 超过 INT_MAX 时此整数重置为零。

原始上下文

我有许多 unsigned int 用作计数器,但希望在特定情况下将它们作为整数传递。

在正常操作下,这些计数将保持在 INT_MAX 的范围内。但是,为了避免在发生异常(但有效)情况时遇到 undefined 实现特定的行为,我希望在这里进行一些有效的转换。

【问题讨论】:

  • 应该是safeConvert?那么,当输入大于 INT_MAX 时,您希望发生什么?在这种情况下你想设置一些标志吗?
  • 虽然有符号运算期间的溢出会产生未定义的行为,但转换为有符号整数类型不会:如果值不能由目标类型表示,则结果是实现定义的。
  • @Hamish 感谢您的拼写错误。当输入大于 INT_MAX 时,最好确保 int 值 > 0。
  • @James 好点,所以从技术上讲,这项任务在没有任何卫生条件的情况下是有效的。所以这里的问题更多是关于我对发生溢出时的值的偏好?
  • 我会使用 if,但我猜这只是我自己

标签: c++ visual-c++ overflow integer-overflow


【解决方案1】:

这也应该有效:

int variable = passed & INT_MAX;

【讨论】:

  • @Jerry:我通常发现写代码比解释要快。代码更密集更简洁,打字速度在某种程度上是限制因素,至少对我来说是这样。
  • 这个解决方案虽然简洁,但正在利用 INT_MAX 的实现相关属性(通常定义为 2**n - 1)。 OP 的具体目标是避免实现定义的行为。最好通过使用类似 typedef char Test[((INT_MAX + 1u) & ((INT_MAX + 1u) - 1)) == 0]; first ;) 来检查这个属性
  • @decltype:我认为这个属性是普遍正确的。但我确实考虑过。无论 INT_MAX+1 是否为 2 的幂,此公式都会将每个整数映射到 (0..INT_MAX) 范围内。
  • 现在这是一个我不考虑自我记录的代码示例(关于 cmets 是否无用存在很大的争论)。
  • @Hamish:是的。我们确实希望那些使用代码的人做的不仅仅是剪切+粘贴到他们的项目中。他们应该添加 cmets、修复变量名称、调整样式,并做任何其他必要的事情来满足他们的项目要求。如果他们对编写该文档的理解不够充分,可以在此处发表评论并询问。
【解决方案2】:

在正常操作下,这些计数将保持在 INT_MAX 的范围内。但是,如果发生异常(但有效)的情况,为了避免遇到未定义的行为,我希望在这里进行一些有效的转换。

高效转换成什么?如果 int 和 unsigned int 的所有共享值都对应,并且您希望其他无符号值(例如 INT_MAX + 1)各自具有不同的值,则只能将它们映射到负整数值。这是默认完成的,可以使用static_cast&lt;int&gt;(my_unsigned) 明确请求。否则,您可以将它们全部映射到 0、-1 或 INT_MIN,或丢弃高位...最简单的方法是:if (my_unsigned &gt; INT_MAX) my_unsigned = XXX...my_unsigned &amp;= INT_MAX 清除高位。但是如果int 溢出,被调用的函数会正常工作吗?也许更好的解决方案是从 64 位整数开始?

【讨论】:

    猜你喜欢
    • 2011-03-08
    • 2012-11-27
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    相关资源
    最近更新 更多