如果我使用input.size() - 1
作为for循环条件,程序将打印“进入循环”。
std::string input;
input = {""};
int i = 0;
for (; i < input.size() - 1; ++i)
{
cout << "Entered the loop" << endl;
}
但是,如果我将input.size() -1
的值传递给整数(checksize
):
std::string input;
input = {""};
int checksize = input.size() - 1;
int i = 0;
for (; i < checksize; ++i)
{
cout << "Entered the loop" << endl;
}
然后程序不会进入循环并且不会打印“进入循环”
我想知道为什么会这样?看来这两段代码对我来说是一样的。
答案 0 :(得分:6)
您是无符号整数的受害者:)
std::string::size()
会返回无符号整数(类型等同于size_t
)。
当编译器评估input.size() - 1
时,这种变为size_t(0) - 1
,并且由于计算是使用无符号整数完成的,而不是-1,因此得到一个非常大的整数number(MSVC 32位编译器打印4294967295
,对应于最大32位无符号整数值2^32 - 1
)。
所以这个循环:
for (int i = 0; i < input.size() - 1; ++i)
相当于:
for (int i = 0; i < /* very big positive number */; ++i)
将打印您的消息许多次。
相反,在第二种情况下,当您评估input.size() - 1
然后将其分配给int
变量(默认为signed
)时,编译器仍会计算size_t(0) - 1
}作为一个非常大的正整数,但是这个数字转换为(signed
)int
,导致checksize
被-1
初始化,你的循环是从未执行过:
for (int i = 0; i < checksize /* -1 */; ++i)
考虑这个可编辑的代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string input;
#ifdef CASE1
for (int i = 0; i < input.size() - 1; ++i)
{
cout << "Entered the loop\n";
}
#else
cout << "input.size() - 1 == " << (input.size() - 1) << '\n';
cout << "SIZE_MAX == " << SIZE_MAX << '\n';
int checkSize = input.size() - 1;
cout << "checkSize == " << checkSize << '\n';
for (int i = 0; i < checkSize; ++i)
{
cout << "Entered the loop\n";
}
#endif
}
如果您使用MSVC和CASE1
(警告级别4 ,我高度建议)编译其/W4
,您将获得 for
循环条件的警告:
cl /EHsc /W4 /nologo /DCASE1 test.cpp test.cpp(10) : warning C4018: '<' : signed/unsigned mismatch
通常会指出您的代码出了问题。
相反,在没有CASE1
的情况下进行编译时,不会发出警告和以下输出(表明永远不会执行for
循环的主体):
cl /EHsc /W4 /nologo test.cpp input.size() - 1 == 4294967295 SIZE_MAX == 4294967295 checkSize == -1
答案 1 :(得分:2)
input.size()
是未签名的数量。所以当它为零时,减去1给出了它的类型的最大值(一个大的正整数,可能是SIZE_MAX
)。
因此输入循环是因为0 < SIZE_MAX
为真。
但是,当您将此大正数转换为int
时,该数字超出了int
的范围。因此发生实现定义的行为,这可能会产生checksize == -1
。然后输入你的循环因为0 < -1
为假。