Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected behavior on adding '\0' to std::string

Tags:

c++

string

stl

Why does the C++ standard allow the following?

#include <iostream>
#include <string>    

int main()
{
    std::string s(10, '\0'); // s.length() now is 10
    std::cout << "string is " << s << ", length is " << s.length() << std::endl;
    s.append(5, '\0'); // s.length() now is 15 
    std::cout << "string is " << s << ", length is " << s.length() << std::endl;
    // the same with += char and push_back 

    // but:
    s += "hello"; // s.length() returns 20 string is "hello"
    std::cout << "string is " << s << ", length is " << s.length() << std::endl;

    return 0;
}

Why does it add 0 and count it? It looks like broken integrity of string, doesn't it? But I checked standard and it is correct behavior.

like image 885
bayda Avatar asked Jul 01 '13 11:07

bayda


3 Answers

Why does standard allows following?

Because the people designing C++ strings decided that such things should be allowed. I'm not sure if anyone that was part of the team that designed C++ strings are on SO... But since you yourself say that the standard allows it, that's the way it is, and I doubt it's about to change.

It's sometimes quite practical to have a string that can contain "anything". I can think of a few instances when I've had to work around the fact that C style strings can't contain zero-bytes. Along with the fact that long C style strings take a long time to find the length of, the main benefit of C++ strings is that they are not restricted to "what you can put in them" - that's a good thing in my book.

like image 78
Mats Petersson Avatar answered Sep 27 '22 22:09

Mats Petersson


Not sure what is problem here.

Adding '\0' in the middle of the std::string changes nothing - null character is treated like any other. The only thing that can change is if you use .c_str() with function that accepts null-terminated strings. But then it's not problem of .c_str(), only with the function that treats '\0' specially.

If you want to know how many characters has this string as if treated like null-terminated string, use

size_t len = strlen(s.c_str());

Note that it's O(n) operation, because that's how strlen works.

If you ask why += operator doesn't add the implicit null character of string literal "hello" to the string, I say the reverse (adding it) is unclear and definitely not what you want 99% of the time. On the other hand, if you want to add '\0' to your string, just append it like a buffer:

char buffer[] = "Hello";
s.append(buffer, sizeof(buffer));

or (even better) drop the char arrays and null-terminated strings altogether and use C++-style replacements like std::string as NTS-replacement, std::vector<char> as contiguous buffer, std::vector as dynamic array with pointers replacement, and std::array (C++11) as standard C array replacement.

Also, (as mentioned by @AdamRosenfield in comments), your string after adding "hello" does have in fact 20 characters, it's probably only that your terminal doesn't print nulls.

like image 30
milleniumbug Avatar answered Sep 27 '22 21:09

milleniumbug


NUL char '\0' is the ending character for c style string, not std::strings. However, it supports this character to get values from a const char pointer so that it can find the end of a c-style string. Otherwise, it is treated just like other characters

like image 43
fatihk Avatar answered Sep 27 '22 22:09

fatihk