I was running this code in VS2019:
#include<iostream>
#include<string>
#include<typeinfo>
using namespace std;
int main() {
string mystring = "hello world";
for (int j = 0; j < 10; j++) {
if (mystring[j + 1] == 'w') {
cout<<"string contains w letter\n";
}
else {
continue;
}
return 0;
}
}
And I realized that when I run it on Debug mode on an x86 platform, everything is ok, but if I change the platform to x64, the following warning appears:
C26451 Arithmetic overflow: Using operator '+' on a 4-byte value and then casting the result to an 8-byte value. Cast the value to the wider type before calling operator '+' to avoid overflow (io.2).
It seems to be related to Usual arithmetic conversions , such that, if the operands are of different types, a conversion is applied to one of them before calculation. But if they are equal, that still happens?
If I print typeid(j).name()
and typeid(1).name()
, it prints int
for both, so what is the reason for this warning? The warning is fixed if I change the if
condition to (mystring[j + static_cast<__int64>(1)] == 'w')
. The explanation, I think, should be that the number '1' is not considered of type int
on x64, or it is but occupies different bits of memory than the int
type on x64.
I would really like to clarify the issue, thanks.
The "C26451" warning is not a standard compiler warning. It's part of the C++ Code Guidelines Checker which is giving you 'recommendations'. For more on this feature, see Microsoft Docs .
In C++ Core Guidelines the specific recommendation the checker is using here is: ES.103: Don't overflow .
The reason this only happens in x64 is because size_t
is 64-bits while int
is 32-bits. In x86, both int
and size_t
are 32-bits.
The std::string
operator[] takes a size_t
. The cleanest simplest fix here is:
for (size_t j= 0; j <10; j++)
You could also address this by explicitly promoting the int
to size_t
before the addition takes place:
if (mystring[size_t(j) + 1] == 'w') {
You could also ignore the warning by adding:
#pragma warning(disable : 26451)
Or you could disable the C++ Core Guidelines Checker.
This is how the std::string
[] operator
defined. It takes std::size_t.
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
That's where the casting is taking place: int -> size_t.
https://www.learncpp.com/cpp-tutorial/fixed-width-integers-and-size-t/
edit: See Chuck Walbourn answer
It seems to be related to Usual arithmetic conversions, such that, if the operands are of different types, a conversion is applied to one of them before calculation. But if they are equal, that still happens?
Your conclusion is incorrect.
VS thinks that j + 1
has the potential to overflow. It recommends that you perform the arithmetic operation, +
, on a wider integral type to reduce the chances of overflow. Note that static_cast<std::size_t>(j) + 1
could, in theory, still overflow but VS does not care about that.
You don't get the warning in x86 mode since the size of std::size_t
and int
are same on that platform.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.