c++arraysstringstring-length

C++ wrong std::string length when using constructor from "empty" char array


I tested this code snippet on different compilers but always got the same result, but I just can't understand why.

unsigned char buffer[0x4000] = {0};
string strText((char*)buffer, 0x4000);  
cout << "strlen((char*)buffer) = " << strlen((char*)buffer) << endl;;
cout << "strText.length() = " << strText.length() << endl;

The output is:

strlen((char*)buffer) = 0
strText.length() = 16384

I'm creating a std::string variable from a unsigned char array (you can also use a signed char array, the result is the same). The array content is "zeroed" (use memset or C++ array initialization, depending on the situation) before passing the variable to the string contructor.

If you get the string length using C style strlen((char*)buffer) function, the result is '0' as expected to be.

If you get the length of the string object using string::length() method the value is equal to the array size passed in the string constructor (16384 in this example). Why?

Also, as a side effect, if you print the content of the string object using std::cout you get a very long empty string (all '0' are replaced with 'space').

Should I perform some additional manipulation on the std::string object in order to get the length I expect (0)?

Thanks


Solution

  • The constructor you use is this constructor (quote from basic_string @ cppreference):

    constexpr basic_string( const CharT* s, size_type count,
                            const Allocator& alloc = Allocator() );
    

    Constructs the string with the first count characters of character string pointed to by s. s can contain null characters. The length of the string is count. The behavior is undefined if [s, s + count) is not a valid range.


    You ask:

    If you get the length of the string object using string::length() method the value is equal to the array size passed in the string constructor (16384 in this example). Why?

    Because you supplied the length to the constructor and a std::string can, as the wiki says, contain null characters.

    Should I perform some additional manipulation on the std::string object in order to get the length I expect (0)?

    Yes, that would be a default-constructed std::string. Just remove buffer and the length when constructing the std::string:

    std::string strText;
    

    If you on the other hand want strText to have reserved space equal to the buffer's space, call the member function reserve:

    std::string strText;
    strText.reserve(sizeof buffer);
    std::cout << strText.length() << '\n'; // prints 0
    

    If you want strText to only have the length up until the first null character in buffer, exclude the length (count) when constructing strText and the std::string constructor will read until a \0 is found and strText.length() will be 0 in your case:

    std::string strText = reinterpret_cast<char*>(buffer);