C++ string.length() 奇怪的行为

C++ string.length() Strange Behavior

我刚遇到一个非常奇怪的问题。我的功能很简单:

int strStr(string haystack, string needle) {

    for(int i=0; i<=(haystack.length()-needle.length()); i++){
        cout<<"i "<<i<<endl;
    }
    return 0;
}

那如果我调用strStr("", "a"),虽然haystack.length()-needle.length()=-1,这不会return0,你可以自己试试...

这是因为.length()(和.size())returnsize_t,这是一个unsigned int。你认为你得到一个负数,而实际上它下溢回 size_t 的最大值(在我的机器上,这是 18446744073709551615)。这意味着您的 for 循环将遍历 size_t 的所有可能值,而不是像您期望的那样立即退出。

为了得到你想要的结果,你可以显式地将大小转换为 ints,而不是 unsigned ints(见 aslgs 答案),尽管对于足够长的字符串这可能会失败(足够over/under流一个标准int)

编辑: 以下评论中的两个解决方案:

  1. (Nir Friedman) 不要像 aslg 的答案那样使用 int,而是包含 header 并使用 int64_t,这将避免上述问题.

  2. (rici) 将您的 for 循环变成 for(int i = 0;needle.length() + i <= haystack.length();i ++){,通过重新排列方程以避免一起减法来一起避免问题。

(haystack.length()-needle.length())

length returns a size_t,换句话说,一个无符号整数。给定字符串的大小,分别为 0 和 1,当您计算差值时,它会下溢并成为 unsigned int 的最大可能值。 (对于 4 个字节的存储,这大约是 42 亿,但可能是不同的值)

i<=(haystack.length()-needle.length())

索引器i被编译器转换成unsigned int来匹配类型。所以你将不得不等到 i 大于 unsigned int 的最大可能值。它不会停止。

解决方案:

你必须把每个方法的结果都转换成int,像这样,

i <= ( (int)haystack.length() - (int)needle.length() )