What is the best alternative to calling strlen() in my for loop condition in C?
I've read that it is bad practice to call strlen() in my for loop condition, because this is an O(N) operation.
However, when looking at alternatives I see two possible solutions:
int len = strlen(somestring);
for(int i = 0; i < len; i++)
{
}
or...
for(int i = 0; somestring[i] != '\0'; i++)
{
}
Now, the second option s开发者_高级运维eems like it might have the advantage of 1) not declaring an unnecessary variable, and 2) should the string length be modified in the loop it should still reach the end as long as the length isn't < i.
However, I'm not sure. Which one of these is standard practice among C programmers?
The second one is usually preferred.
The other popular form is
for (char* p = something; *p; p++)
{
// ... work with *p
}
Yet another one is
char* p = something;
char c;
while ((c = *p++))
{
// ... do something with c
}
(the extra ()
around assignment are needed to make some suspicious compilers not issue a warning stating I might mean comparison inside while
condition)
Indeed, strlen
is quite slow, because it must go through the whole string looking for trailing 0. So, strlen
is essentially implemented as
int s = 0;
while (*p++) s++;
return s;
(well, in fact a slightly more optimized assembler version is used).
So you ought to avoid using strlen
if possible.
These are preferred:
for (int i = 0; str[i]; ++i)
for (char* p = str; *p; ++p)
If some part of your loop can overwrite the NUL char at the end of your string, the version that calls strlen will still finish before then end of your buffer. The second version could overrun the buffer and party all over somebody else's memory. The strlen version is also easier to understand at a glance.
Usually the second. If nothing else, the first one has to traverse the string twice: once to find the length, and again to operate on each element. On the other hand, if you have code already written strlen, it may be easier to just hoist the strlen call out of the loop and still get most of the benefit.
The first approach looks like this for me :
while(..) { Test end of string } /* strlen */
while(..) { Your Code } /* processing */
While the second approach looks like :
while(..) { Your Code + Test end of string } /* both */
IMHO, both approach compute roughly the same number of operations, and I consider them equivalent. Also, strlen is quite optimized, as already mentioned, and well tested. Moreover, the second approach looks like premature optimization :) You'd better test/profile your code if necessary and then optimize (after all, it is only a linear algorithm).
You may however consider the second approach if the processing may possibly stop long before the end of the string (e.g., find the first occurence of a word).
As other answers have stated, while both options work the second is more usual. But comparind chars against '\0' is not something I would recommend. The type of '\0' is int, not char. That is, it has the same type as 0. However, it's more bug prone to write '\0' than just 0, because an accidental backspace can convert it into '0', which isn't the same at all. This bug may not easily be spotted by someone casually reading the code.
精彩评论