Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is compile-time "strlen()" effective?

Sometimes it is necessary to compare a string's length with a constant.
For example:

if ( line.length() > 2 )
{
    // Do something...
}

But I am trying to avoid using "magic" constants in code.
Usually I use such code:

if ( line.length() > strlen("[]") )
{
    // Do something...
}

It is more readable, but not efficient because of the function call.
I wrote template functions as follow:

template<size_t N>
size_t _lenof(const char (&)[N])
{
    return N - 1;
}

template<size_t N>
size_t _lenof(const wchar_t (&)[N])
{
    return N - 1;
}

// Using:
if ( line.length() > _lenof("[]") )
{
    // Do something...
}

In a release build (VisualStudio 2008) it produces pretty good code:

cmp    dword ptr [esp+27Ch],2 
jbe    011D7FA5 

And the good thing is that the compiler doesn't include the "[]" string in the binary output.

Is it a compiler specific optimisation or is it a common behavior?

like image 254
Dmitriy Avatar asked Sep 08 '09 02:09

Dmitriy


2 Answers

Why not

sizeof "[]" - 1;

(minus one for the trailing null. You could do sizeof "[]" - sizeof '\0', but sizeof '\0' is often sizeof( int ) in C, and "- 1 " is perfectly readable.)

like image 102
William Pursell Avatar answered Sep 28 '22 01:09

William Pursell


I think most compilers will optimize it away when optimizations are enabled. If they're disabled, it might slow your program down much more than necessary.

I would prefer your template functions, as they're guaranteed to not call strlen at runtime. Of course, rather than writing separate functions for char and wchar_t, you could add another template argument, and get a function which works for any type:

template <typename Char_t, int len>
int static_strlen(const Char_t (&)[N] array){
  return len / sizeof(Char_t) - 1;
}

(As already mentioned in comments, this will give funny results if passed an array of ints, but are you likely to do that? It's meant for strings, after all)

A final note, the name _strlen is bad. All name at namespace scope beginning with an underscore are reserved to the implementation. You risk some nasty naming conflicts.

By the way, why is "[]" less of a magic constant than 2 is?

In both cases, it is a literal that has to be changed if the format of the string it is compared to changes.

like image 34
jalf Avatar answered Sep 28 '22 01:09

jalf