[英]How do usual arithmetic conversions work?
I was running this code in VS2019:我在 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:我意识到,当我在 x86 平台上以调试模式运行它时,一切正常,但如果我将平台更改为 x64,则会出现以下警告:
C26451 Arithmetic overflow: Using operator '+' on a 4-byte value and then casting the result to an 8-byte value.
C26451 算术溢出:对 4 字节值使用运算符“+”,然后将结果转换为 8 字节值。 Cast the value to the wider type before calling operator '+' to avoid overflow (io.2).
在调用运算符“+”之前将值转换为更广泛的类型以避免溢出 (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?如果我打印
typeid(j).name()
和typeid(1).name()
,它会为两者打印int
,那么这个警告的原因是什么? The warning is fixed if I change the if
condition to (mystring[j + static_cast<__int64>(1)] == 'w')
.如果我将
if
条件更改为(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.我认为,解释应该是数字'1'不被认为是x64上的
int
类型,或者它占用了memory的不同位,而不是x64上的int
类型。
I would really like to clarify the issue, thanks.我真的很想澄清这个问题,谢谢。
The "C26451" warning is not a standard compiler warning. “C26451”警告不是标准的编译器警告。 It's part of the C++ Code Guidelines Checker which is giving you 'recommendations'.
它是 C++ 代码指南检查器的一部分,它为您提供“建议”。 For more on this feature, see Microsoft Docs .
有关此功能的更多信息,请参阅Microsoft Docs 。
In C++ Core Guidelines the specific recommendation the checker is using here is: ES.103: Don't overflow .在C++ 核心指南中,检查器在这里使用的具体建议是: ES.103:不要溢出。
The reason this only happens in x64 is because size_t
is 64-bits while int
is 32-bits.这只发生在 x64 中的原因是
size_t
是 64 位,而int
是 32 位。 In x86, both int
and size_t
are 32-bits.在 x86 中,
int
和size_t
都是 32 位。
The std::string
operator[] takes a size_t
. std::string
运算符[] 采用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:您还可以通过在添加之前将
int
显式提升为size_t
来解决此问题:
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.或者您可以禁用 C++ 核心指南检查器。
This is how the std::string
[] operator
defined.这就是
std::string
[] operator
的定义方式。 It takes std::size_t.它需要 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.这就是强制转换发生的地方:int -> size_t。
https://www.learncpp.com/cpp-tutorial/fixed-width-integers-and-size-t/ https://www.learncpp.com/cpp-tutorial/fixed-width-integers-and-size-t/
edit: See Chuck Walbourn answer编辑:见 Chuck Walbourn 的回答
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. VS 认为
j + 1
有溢出的可能。 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.请注意,理论上
static_cast<std::size_t>(j) + 1
仍然可能溢出,但 VS 并不关心这一点。
You don't get the warning in x86 mode since the size of std::size_t
and int
are same on that platform.您不会在 x86 模式下收到警告,因为该平台上
std::size_t
和int
的大小相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.