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