Printing string views

This is something I've seen go wrong a couple of times, and so I thought I'd have a post on this to act as a handy reference.

Let's say you had code that used to do this:

void some_fun(const std::string& s) {
 // ...
 printf("awesome string: %s", s.c_str());
}

You like that there are no string copies and go about things happily. However, at some point someone mentions that your callers didn't actually have a string to begin with, so using your function forces them to go allocate and prepare a string. You look around and find the nifty std::string_view ref and decide that's what you'll use instead.

void some_fun(std::string_view s) {
 // ...
 printf("awesome string: %s", s.data());
}

Things compile and all is seemingly well... until your program start printing garbage. What happened?

When you use std::string_view, there is no requirement that the string be null terminated. That's a pretty good thing, because it lets you refer to string within larger buffers, or get zero-copy slices of substrings and so on.

When you use a printf-like function, however, now you're going to have to specify an string length explicitly.

void some_fun(std::string_view s) {
 // ...
 printf("my string is %.*s", static_cast<int>(s.size()), s.data();
}

In fact, you might also want to check the string length to make sure that there is no data loss when doing the cast. You might inline the check or simply leverage a known library to do that for you.

You can go play with this sample to see it in action.

Happy string printing!

Tags:  coding

Home