警告C26451:算术溢出

Warning C26451: Arithmetic overflow

本文关键字:溢出 C26451 警告      更新时间:2023-10-16

如何解决这些警告?

// midiNote is a double as it is used in floating point equation
// v is int because that's informative that the function wants whole numbers
void setMidiNote(int v) { midiNote = v-48;  }

警告C26451算术溢出:在4个字节值上使用操作员' - ',然后将结果施放为8个字节值。在调用操作员" - "之前将值施放给更宽的类型,以避免溢出(io.2(。

// input should be 0 to 10 integer, and dank will be odd integers only
// dank is a double, it is ultimately used in a floating point equation
void setDarkIntensity(int v) { dank = v * 2 + 1; }

警告C26451算术溢出:在4个字节值上使用操作员'*',然后将结果施放为8个字节值。在调用操作员"*"以避免溢出之前,将值施放为更宽的类型(io.2(。

警告C26451算术溢出:在4个字节值上使用操作员' ',然后将结果施放为8个字节值。在调用操作员为" "之前,将值施放为更宽的类型,以避免溢出(io.2(。

我相信这是VS2019中的错误。它不再在VS2022中标记。

例如,这会产生警告

double test2(int n)
{
     return 4.0 * (n - 1);
}

但这不是

int test2a(int n)
{
    return 4 * (n - 1);
}

然而,后者的不确定行为的风险要大得多。乘以4大大增加了UB的风险,因为大量的N会产生UB。多么伟大?好吧,在大约40亿可能的值中,n只有一个可能的值在溢出的第一个示例中。在第二个中,大约有30亿n S可以超越/下水。为什么?因为整数算术是不可能的。

可以说,要警告,要警告几乎可以警告INT上的任何算术操作。

此答案显示了一种在vs 2019中禁用此警告的方法。

警告C26454:算术溢出:' - '操作在编译时间(io.5(

时产生负面的无符号结果

但是,从VS2022开始,Microsoft不再为此产生C26451警告。它也不显示在-wall下。他们显然看到了光。

警告告诉您,您的计算有可能在转换为结果(较大(类型之前溢出原始(较小(类型。在第一种情况下,如果v是min_int(-2 31 (,则减去收集将下流,从而导致不确定的行为(可能是大的正数(,然后将其存储在midiNote中。为避免警告,请先转换为较大的类型:

midiNote = double(v) - 48;

对于您的第二个示例类似。

虽然您知道setMidiNote不会带有这个问题的值,但 compiler 不知道并发出警告,以提醒您可能出现问题的可能性。

我通过查看一些Microsoft文档解决了问题,但是您也可以将变量更改为long long类型(我知道在顶部(。它摆脱了我的错误。希望他们很快解决这个问题。

我通过将变量的类型更改为"未签名的__int64"来摆脱警告。这就是微软的开发人员社区建议!

要解决您的问题,将参数V铸造为64位类型:

void setMidiNote(int v) { midiNote = static_cast<int64_t>(v) - 48; }

void setDarkIntensity(int v) { dank = static_cast<int64_t>(v) * 2 + 1; }

在VS 2019上测试16.9.6

来源:https://develovercommunity.visualstudio.com/t/invalid-error-c26451/279594#t-n404080https://learn.microsoft.com/en-us/cpp/code-quality/c26451

static_cast&lt;&gt;((是推荐的解决方案。.目前我正在阅读的书对此新铸造惯例进行了很大的收益。作为C风格..(根据文献(..我想知道..是否将其宣布为自动。听起来矢量可以做到……

void setDarkStrentty(auto v({dank = v * 2 1;}

施放到您想要的数据类型上,然后一直使用:

// midiNote is a double as it is used in floating point equation
// v is int because that's informative that the function wants whole numbers
void setMidiNote(int v) { midiNote = static_cast<double>(v) - 48.0;  }
// input should be 0 to 10 integer, and dank will be odd integers only
// dank is a double, it is ultimately used in a floating point equation
void setDarkIntensity(int v) { dank = static_cast<double>(v) * 2.0 + 1.0; }

曾经是整数操作比浮点快得多,但是在现代CPU上不再是正确的。

使用2.0代替2迫使v的铸件隐式地施放到double,但显式始终更清楚。

奖励建议:考虑验证调试构建中的任何假设。将来更改代码时,这将有助于避免破坏这些假设。类似:

// input should be 0 to 10 integer, and dank will be odd integers only
// dank is a double, it is ultimately used in a floating point equation
void setDarkIntensity(int v) 
{ 
    assert(v >= 0 && v <= 10);
    dank = static_cast<double>(v) * 2.0 + 1.0; 
}

奖励建议2:如果这些功能不是类的一部分,我会标记它们inline,因此优化器有更好的机会使用这些简单的功能来完成其操作。如果它们是班级定义的一部分,那么这是隐式完成的。