警告 C26451:算术溢出(减去两个整数时)
Posted
技术标签:
【中文标题】警告 C26451:算术溢出(减去两个整数时)【英文标题】:Warning C26451: Arithmetic overflow (when subtracting two ints) 【发布时间】:2020-04-26 16:09:07 【问题描述】:当执行以下代码行时:
int max = 50, min = -30;
double num = rand() % (max - min) - min;
我从 Visual Studio 2019 收到以下警告:
警告 C26451 算术溢出:对 4 字节值使用运算符“-”,然后将结果转换为 8 字节值。在调用运算符 '-' 之前将值转换为更广泛的类型以避免溢出 (io.2)。
我不确定这是如何适用的,因为我正在取一个 double 的模数,它将返回一个整数,然后从中减去另一个整数,然后将它存储在一个 double 中(我相当确定不是问题)。
这是一个错误还是我正在做一些可能导致截断等的事情?
谢谢
【问题讨论】:
如果你想在[min;max)
之间生成一个数字,你的表达式不应该是rand() % (max - min) + min
吗?
首先,这是一个警告,而不是错误。该代码是有效的,其含义是明确定义的。拒绝编译此代码的编译器不符合语言定义。显然编译器编写者认为这样的代码可能容易出错,而您通过使用将警告变为错误的设置来放大这种观点。
@geza 哦哇是的哈哈,确实应该加分!谢谢
【参考方案1】:
差异(在两个减法中)可能导致溢出。如果从正值中减去负值,或者从负值中减去正值,则可能会发生溢出。
例如,如果从最大可能值中减去负数,则会出现溢出。
由于您有更广泛的目标类型,因此您可能希望这个更广泛的结果适合这个更广泛的类型而不会溢出。这不会发生,除非您转换您的操作数之一。
我认为在这里进行这样的转换并不实际,因为您使用%
运算符,这不适用于double
。无论如何它不会处理溢出,只是因为这里的范围不能超过rand()
的范围。
显然,如果您想修复rand()
的可能溢出问题,您将需要std::uniform_int_distribution
与您的范围。这将解决其他 rand()
问题(线程安全和不好的随机性),但也会增加一些复杂性。
但是如果你总是有 -30 到 50 的范围,就没有溢出,你可以把它当作一个错误的警告。如果您确实拥有int max = 50, min = -30;
,我什至将其视为发出此警告的静态分析错误。当然静态分析无法预测rand()
的结果,但是有%
可以截断它。如果您在意,可以使用帮助 > 发送反馈 > 报告问题。
【讨论】:
非常感谢 - 我现在明白了,我会看看我的程序是否需要捕捉这些极端情况。以上是关于警告 C26451:算术溢出(减去两个整数时)的主要内容,如果未能解决你的问题,请参考以下文章
C26451 算术溢出访问 CStringArray 中的项目