Skip to content

15 Beginner The Hundred

The String That Stops Early

five characters go in; how many come out?

#include <iostream>
#include <string>

int main() {
    std::string a = "ab\0cd";
    std::string b("ab\0cd", 5);

    std::cout << "a.size() = " << a.size() << '\n';
    std::cout << "b.size() = " << b.size() << '\n';
}

Run it. What are the two sizes?

Answer

a.size() = 2 and b.size() = 5. Same literal — but a never saw anything past the \0.

Why

The literal "ab\0cd" is a perfectly real six-character array: {'a','b','\0','c','d','\0'}. But std::string's const char* constructor receives only a pointer — no length — so it does the only thing it can: count characters until the first NUL, exactly like strlen. That makes a a copy of just "ab"; the cd exists in the literal but is never read. std::string itself is entirely happy to hold NULs — it stores its length separately — which is why the (pointer, count) constructor hands b all five characters. The trap also runs in reverse: pass a NUL-holding string to a C API via .c_str() and the C side stops at the first \0 again.

The fix

Tell the constructor the real length, or use the s literal suffix (C++14), which knows the size of the array it came from:

std::string b("ab\0cd", 5);       // explicit count: all five characters

using namespace std::string_literals;
std::string c = "ab\0cd"s;        // c.size() == 5

Takeaway: a bare char* is C-string territory — anything after the first \0 is invisible unless you pass a length or use the s suffix.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo

Open in Compiler Explorer ↗ Quiz this entry