Reputation: 1147
How do I solve these warnings?
// 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; }
Warning C26451 Arithmetic overflow: Using operator '-' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '-' to avoid overflow (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; }
Warning C26451 Arithmetic overflow: Using operator '*' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '*' to avoid overflow (io.2).
Warning C26451 Arithmetic overflow: Using operator '+' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator '+' to avoid overflow (io.2).
Upvotes: 29
Views: 56921
Reputation: 1208
Cast to the data type you want as early as possible and then use it all the way through:
// 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; }
It used to be that integer operations were much faster than floating point, but that is no longer true on modern CPUs.
Using 2.0
instead of 2
forces the casting of v
to double
implicitly but being explicit is always more clear.
Bonus Advice: Consider verifying any assumptions in debug builds. It will help to avoid breaking those assumptions when you change the code in the future. Something like:
// 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;
}
Bonus Advice 2: If these functions are not part of a class, I would label them inline
so the optimizer has a better chance of doing its thing with these simple functions. If they're part of the class definition, then this is already done implicitly.
Upvotes: 0
Reputation: 1
static_cast<>() is the recommended solution.. The book I'm reading at the moment makes a big deal of this new casting convention.. Just using (v) is regarded as C style.. (According to the literature)..I wonder.. if it will work just to declare v as auto. Sounds like Vector is up to something....
void setDarkIntensity(auto v) { dank = v * 2 + 1; }
Upvotes: 0
Reputation: 4299
I believe this is a bug in VS2019. It no longer is flagged in VS2022.
For instance this produces the warning
double test2(int n)
{
return 4.0 * (n - 1);
}
But this doesn't
int test2a(int n)
{
return 4 * (n - 1);
}
Yet, the risk of undefined behavior is much greater for the latter. Multiplying by 4 greatly increases the risk of UB since a far large set of n's will produce UB. How great? Well, there is only one possible value of n
out of around 4 billion possible values in the first example that overflows. In the second there are around 3 billion n
s that would over/underflow. Why? Because integer arithmetic would be impossible if every expression with more complexity than adding 0 or multiplying by 1 was flagged because it might overflow.
Arguably, for a warning to be set that high virtually any arithmetic operation on ints would be warned.
This answer shows a way to disable this warning in VS 2019 in the code analysis rule set editor.
However, Microsoft, as of VS2022, no longer produces a squiggle C26451 warning for this. Nor does it show up under -Wall. They apparently saw the light.
Upvotes: 20
Reputation: 21
To fix your issue, cast parameter v to a 64 bit type:
void setMidiNote(int v) { midiNote = static_cast<int64_t>(v) - 48; }
void setDarkIntensity(int v) { dank = static_cast<int64_t>(v) * 2 + 1; }
Tested on VS 2019 16.9.6
Source: https://developercommunity.visualstudio.com/t/invalid-error-c26451/279594#T-N404080 https://learn.microsoft.com/en-us/cpp/code-quality/C26451
Upvotes: 1
Reputation: 866
I got rid of the warning by change the type of the variable to "unsigned __int64". That's what the Developer Community in Microsoft suggests!
Upvotes: 3
Reputation: 1497
I resolved the problem by looking at some Microsoft Docs, but you could also change your variable into a long long
type(over the top, I know). It got rid of the errors for me. Hopefully they address this soon.
Upvotes: 3
Reputation: 32727
The warnings are telling you that there is a chance that your calculation will overflow the original (smaller) type before conversion to the result (larger) type. In the first case, if v
is MIN_INT (-231), the subtraction will underflow, resulting in Undefined Behavior (likely a large positive number) that will then be stored in midiNote
. To avoid the warning, convert to the larger type first:
midiNote = double(v) - 48;
Similarly for your second example.
While you can know that setMidiNote
will not be called with values that will have this problem, the compiler doesn't know and issues this warning to alert you to the potential for a problem.
Upvotes: 7