c++ - for 循环中奇怪的 std::string::size()

标签 c++ for-loop size unsigned unsigned-integer

如果我使用 input.size() - 1 作为 for 循环条件,程序将打印“Entered the loop”。

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;
}

那么程序就不会进入循环,也不会打印“Entered the loop”

我想知道为什么会这样?这两段代码对我来说似乎是一样的。

最佳答案

你是无符号整数的受害者:)

std::string::size() 返回一个无符号整数(类型等同于size_t)。

当编译器评估 input.size() - 1 时,这种类型变为 size_t(0) - 1,因为计算是用 完成的无符号 整数,而不是 -1 你会得到一个非常大的整数(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 计算为一个非常大的正整数,但随后该数字将转换为(有符号) 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 和 /W4 编译它的 CASE1(警告级别 4,我强烈建议),您会收到针对您的 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

关于c++ - for 循环中奇怪的 std::string::size(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37090091/

相关文章:

c++ - 如何正确检测 GCC 版本中可用的 C++11 功能?

Java 多线程 |寻找所有的可能性

在c中组合两个数组,导致错误的函数

size - MSMQ队列大小是否有限制?

c++ - 使用 ios::ate 写入 ofstream 会覆盖现有文件

c++ - 重载的模板方法未按预期解析

c# - 从 C++ 程序转换时使用 C# 泛型

java - 在java中打印用户输入字符串的每三个字符

c - 为什么即使添加未初始化的全局变量,size 命令显示的 bss 值也不会增加?

java如何定义newFixedThreadPool的大小