Home > Back-end >  Convert std::string to char* when string has nulls in middle
Convert std::string to char* when string has nulls in middle

Time:09-21

char* convert()
{    
    std::string data = "stack\0over\0flow";
    return data.c_str();
}

This will return pointer and upon building the string from it on the caller it will have stack instead of complete string. Is there a workaround for this with out changing input and return types in c 11? I want to rebuild the entire string on the caller side from char*.

CodePudding user response:

Convert std::string to char* when string has nulls in middle

In order to convert a std::string that has nulls in the middle to a char*, you must first have a std::string that has nulls in the middle. You don't have such string.

Because you used the constructor std::string(const char*), the string that you created treated the passed pointer as a pointer to first element of a null terminated string, and as such the std::string only contains "stack".

You can use:

const auto& str = "stack\0over\0flow";
std::string data(str, std::size(str) - 1);

This will return stack instead of complete string

If the string were to actually contain "stack\0over\0flow", then c_str will return a pointer to the first element of the complete string "stack\0over\0flow".

If you treat the pointer as a pointer to null terminated string, then the first null terminator character terminates the null terminated string. There is no way to avoid that if you treat the pointer as a pointer to null terminated string. So, if you wish to avoid the string being terminated by the first null terminator character, then don't treat it as a pointer to a null terminated string (such as when you used the string literal as a pointer to null terminated string in your example).

However, that's mostly a moot issue since the pointed string will have been deallocated and the returned pointer will be dangling when the function returns. Attempting to access through the danging pointer will result in undefined behaviour.

Furthermore, c_str always returns a const char* and never char*.

CodePudding user response:

To be able to use the full string with the \0's safely. you must put the data in a buffer. E.g. like this :

#include <iostream>
#include <array>
#include <vector>

template<std::size_t N>
auto make_buffer(const char(&chars)[N])
{
    // note returing an object uses RVO and nothing is left dangling.
    std::array<char, N> buffer{};
    for (std::size_t n = 0; n < N;   n) buffer[n] = chars[n];
    return buffer;
}

int main()
{
    auto buffer = make_buffer("stack\0over\0flow");

    // this is the closest you can get to having a char*
    // pointing to ALL the data.
    char* data_ptr = buffer.data();

    // but you still must rely on the buffer size
    // for correct looping over the valid values!
    for (std::size_t n = 0; n < buffer.size();   n)
    {
        std::cout << data_ptr[n];
    }
    std::cout << std::endl;

    // But with a buffer like this a range based for loop is recommended
    for (const auto c : buffer)
    {
        std::cout << c;
    }
    std::cout << std::endl;

    return 0;
}
  • Related