在循环条件中使用strlen()比检查null字符更慢吗?

时间:2010-08-02 13:07:18

标签: c strlen string-length

我读过strlen的使用比这样的测试更贵:

我们有一个字符串x长100个字符。

我认为

for (int i = 0; i < strlen(x); i++)

比这段代码贵:

for (int i = 0; x[i] != '\0'; i++)

这是真的吗?也许第二个代码在某些情况下不起作用,所以最好使用第一个代码吗?

下面会更好吗?

for (char *tempptr = x; *tempptr != '\0'; tempptr++)

8 个答案:

答案 0 :(得分:27)

for (int i=0;i<strlen(x);i++)

此代码每次迭代都会调用strlen(x)。因此,如果x的长度为100,则strlen(x)将被调用100次。这非常昂贵。此外,strlen(x)每次都以{for循环'相同的方式迭代x。这使得O(n ^ 2)复杂度。

for (int i=0;x[i]!='\0';i++)

此代码不调用任何函数,因此比前一个示例快得多。由于它只遍历循环一次,因此它是O(n)复杂度。

答案 1 :(得分:11)

第一个代码在i的每次迭代中检查x的长度,并且需要O(n)来找到最后的0,所以它需要O(n ^ 2),第二种情况是O(n)

答案 2 :(得分:4)

是的,你的第二个可能不会百分之百的时间工作,但它会很轻微。这是因为当使用strlen()时,您每次都必须调用该方法。更好的方法就是这样

int strLength = strlen(x);
for (int i = 0; i < strLength; i++)

希望这有帮助。

答案 3 :(得分:2)

我可以假设在第一个变体中,每次迭代都会找到strlen,而在第二个变体中,您不会这样做。
试试这个来检查:

int a = strlen(x); 
for (int i = 0; i < a; i++) {...}

答案 4 :(得分:2)

如果没有,则没有编译优化。是的,因为strlen每次都会迭代字符串的每个字节,第二次实现只会执行一次。

答案 5 :(得分:2)

我想编译器可以优化(检查Gregory Pakosz注释)你的第一个for循环,这样你就会这样:

int len = strlen(x);
for (int i = 0; i < len; i++)

仍然是O(n)

无论如何,我认为你的第二个for循环会更快。

答案 6 :(得分:0)

当然第一个比第二个花费的时间更长。它们实际上根本不做同样的事情 - 第一个是每次计算字符串的长度;第二个是(有效地)只做一次。

第一个版本相当于:

for (int i=0; x[i] != 0; i++)
  for (int j=0; j<i; j++)
    ;

也许你的意思是“调用库strlen()比实现我自己的更高效吗?”当然,答案就是“它取决于”。您的编译器可能具有strlen()的内部版本,这些版本的优化超出了您对源的期望,您可能在一个功能调用昂贵的平台上(现在很少见),等等。

唯一的答案是一般的和正确的是“简介并找出”。

答案 7 :(得分:0)

值得注意的是,如果您还没有根据包含字符串的缓冲区大小测试索引,那么您可能会遇到缓冲区溢出问题。根据您使用此代码所做的事情,这可能是也可能不是实际问题,但是进行额外检查很少会受到伤害,这是一个很好的习惯。

我建议:     for(i = 0; i&lt; buf_size&amp;&amp; x [i]!='\ 0'; i ++)

其中:

  • buf_size是缓冲区的预定大小。如果x是数组,则为sizeof(x);如果x是指针,则应该具有可用的缓冲区大小。
  • 我从循环中删除了i的声明,因为它只是有效的c99。如果您只是在c99下进行编译,请随时将其重新插入。