c++stdoutiostreamnull-characternon-printing-characters

Is it safe to output a NULL char to std::cout?


Even though it is a very little problem, but every time when I need to print out some data in a loop, how to arrange the separating char always annoys me.

For example:

std::set<int> my_data { 1, 2, 3 };
bool is_first { true };
std::cout << '{';
for( auto i : my_data ) {
    if( is_first )
        std::cout << i;
    else
        std::cout << ',' << i;
    is_first = false;
}
std::cout << '}';

Or:

std::set<int> my_data { 1, 2, 3 };
size_t cnt { 0 };
cout << '{';
for( auto i : my_data )
    if( ++cnt == my_data.size() )
        std::cout << i;
    else
        std::cout << i << ',';
std::cout << '}';

You can see in my codes, in order to insert a separating char at correct places, I used 4~5 lines in the loop while the real job is merely std::cout << i;!

So, I often do it like this:

std::set<int> my_data { 1, 2, 3 };
char sep { '\0' };
cout << '{';
for( auto i : my_data ) {
    std::cout << sep << i;
    sep = ',';
}
std::cout << '}';

Is it safe to output a NULL ('\0') char to std::cout? I'm using this method mainly in my daemon programs, so in this way they mainly prints some log text to std::cout/std::cerr, or other text files in a Linux filesystem.

The result files(log file), mainly are read by some cli tools such as more/less/tail/head.

In this way, will I encounter any crash? In other words, would the NULL char be ignored silently by the file system/terminal/stdout/...?


Solution

  • Would the NULL char be ignored silently by fs/terminal/stdout/...?

    File system:
    No, the null character will not be ignored. It would get saved in the file just like every other character. Whether or not this will mess up your cli tools depends on the tools, and potentially on how you use them.

    Terminal:
    Depends on the terminal. The ones I've sent null characters to have ignored the character, but others are free to display it however they want. (A space or some variant on a question mark are two common approaches for non-printable characters.)

    stdout:
    No, the null character will not be ignored. The null character will be passed on to the destination (which is often the terminal, but could be redirected to a file).

    In summary, std::cout << '\0'; is likely to have no visible effect, but your mileage may vary.

    Caveat, esp. for future readers: don't confuse '\0' with "\0". Streaming the former sends a null character through std::cout, while streaming the latter sends no characters, the same as if it was the empty string. On a related note, if you change the definition of sep to const char* sep = ""; and the later assignment to sep = ",";, you can get the desired formatting and avoid streaming the null character.