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

我已经读过使用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++) 

 for (int i=0;i 

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

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

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

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

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

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

希望这可以帮助。

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

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

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

哪个仍然是O(n)

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

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

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

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

第一个版本相当于:

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

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

唯一的答案是一般的和正确的是“简介和发现”。

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

我建议:for(i = 0; i

哪里:

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