0
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*.

4
  • 3
    Be careful: data will be destroyed if it goes out of scope. Thus, your code will return a dangling pointer if return type is pointer. Commented Sep 21, 2021 at 6:45
  • Oh wait - you are right. eerorika's answer below is the best guidance. Commented Sep 21, 2021 at 7:18
  • @vmario It is kind of correct, it returns the full string of data - it's just that you have to construct the std::string in a different way if you want to include NUL in the middle. Commented Sep 21, 2021 at 7:18
  • What do you want to do when you get a char*, you lost ALL information on the lenght of the original string AND you can't loop until the terminating zero. This will not be useful. Commented Sep 21, 2021 at 7:38

2 Answers 2

6

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*.

Sign up to request clarification or add additional context in comments.

Comments

0

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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.