4

I can see it listed as one of the modern C++ idioms, but what it is exactly?

Is it just a type of copy elision?

  • 3
    Possible duplicate of [Evaluating strlen at compilation time?](https://stackoverflow.com/questions/46101386/evaluating-strlen-at-compilation-time) One of comments there is the answer on your question. – 273K Apr 08 '18 at 04:11
  • @S.M. no that is not the answer to my question. For an proper answer see the one bellow. –  Apr 12 '18 at 12:35

2 Answers2

9

You might know that std::strlen loops over the whole string. This can be inefficient in some cases, as it means that the CPU has to start counting characters, which reduces cache locality for other stuff.

But in most cases, the compiler is able to optimize std::strlen and count the number of characters of the string itself instead of making the resulting program do it. This is sometimes called strlen elision (because it elides the call to strlen).

A simple example of std::strlen would simply get optimized completely.

#include <cstring>

int main() {
    return std::strlen("hi");
}

Under -O3 the resulting assembly is

main: # @main
  mov eax, 2
  ret

Even under -O0 no loop is generated!

Now this is a rather simple example, but it works even for a bit more complicated usages of std::strlen.

#include <cstring>

int main(int argc, char**) {
    const char *string;
    if (argc == 1)
        string = "hello";
    else if (argc == 2)
        string = "world";
    else if (argc == 3)
        string = "!";

    return std::strlen(string); 
}

Here the strings are completely optimized away, as well as the std::strlen call.

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
  • very good thanks. Do you think such a optimization might be possible with no string literals involved? –  Apr 08 '18 at 05:01
  • 1
    @DusanJovanovic Not really. If there are not string literals involved, then the compiler has to way of knowing how long the string really is. But the compiler can always surprise you :) – Rakete1111 Apr 08 '18 at 05:07
  • 2
    With 'full program optimisation' (as performed by Microsoft's linker) then lots of things are possible. For example, if a string literal is passed to a function which in turn calls strlen, and that function gets inlined by the linker, then the call to strlen becomes elidable. If the linker is as clever as the compiler, that is. – Paul Sanders Apr 08 '18 at 07:51
0

With all due respect to Rakete, it seems self-evident to me that if the compiler understands the semantics of strlen, and if the string in question is known at compile time, then the compiler can just emit a constant rather than evaluating the length of the string (by whatever means) at runtime. That's all that is happening here. Trust Microsoft's marketing department to hype-up such a simple feature.

What interests me about all this is the increasing trend for (optimising) compilers to treat commonly used runtime library functions as intrinsics and emit better code for them when it can. This has been going on for a while - memcpy and memset are obvious examples - but I was playing around in Godbolt's Compiler Explorer recently and was amazed to see gcc replace this:

printf (" ");

with this:

putchar (' ');

Shocked? Me too, and I'm not sure I like it. I might have a custom printf that does something special and this sort of trickery would come as a rude surprise. Seems to me a big risk (by the compiler writers) for such a small gain.

Paul Sanders
  • 24,133
  • 4
  • 26
  • 48
  • 2
    If you have a custom `printf` then you are not writing standard C or C++, and you're on your own. – Pete Becker Apr 08 '18 at 12:37
  • You think? Where in the standard does it say 'thou shalt not replace a standard library function' (by writing a replacement and linking it in)? Granted, for something like strlen that might be treated as an intrinsic this is most unwise, but for _printf_? I really think the compiler should leave calls to a function as complex as that alone. That's the point I was trying to make - that monkeying with a call to printf is way beyond what most people would expect the compiler to do - not that I necessarily want to do it. – Paul Sanders Apr 08 '18 at 17:53
  • 2
    Names of standard library functions are names with external linkage. As such, they are reserved, and the behavior of a program that defines any of those names is undefined. [reserved.names]/2. – Pete Becker Apr 08 '18 at 19:29
  • In other words, you are welcome to write a ``myprintf``, but you shouldn't try to write your own ``printf``. – Chuck Walbourn Apr 09 '18 at 18:01
  • OK that's fair enough, and I wasn't planning to anyway, but I really do think that the compiler writers have gone too far here. There's nothing to gain, why bother? – Paul Sanders Apr 09 '18 at 20:47
  • I'm pretty sure the compiler only does this when you are using the printf declaration from the original header file. And this original header file will have some pragma like decorations on the identifier so it never confuses his printf with your printf. Remember that standard header libraries don't need to be C++, they can use all magic the compiler vendor provides. – Lothar May 17 '20 at 20:01