在循环条件中使用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下进行编译,请随意将其重新插入。