call me Steve
call me Steve

Reputation: 1727

Converting "unsigned char *" to "char *" (and string)

I am working on a pet project with the libsodium library, and found that converting unsigned char * to char * was less straight forward than I imagined. Also I first was confused because the tests were passing in Release mode and only bit later I realised they were not passing in Debug mode. So I came up with the following:

std::string string_from_uchar(const unsigned char * c, unsigned long long lc)
    {
        unsigned char * cc = new unsigned char[lc+1] ;
        std::strncpy((char *) cc, (char *) c, lc);
        cc[lc] = 0;
        char* cr = reinterpret_cast<char *> (cc);
        std::string ret(cr);
        delete[](cr);
        return ret;
    }

While it now passed the tests, I was be grateful if someone could check if it is the right way of doing it (for instance would that work on another environment like gcc or clang?).

Upvotes: 1

Views: 994

Answers (1)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385305

You're massively over-thinking this.

The copy is redundant, as is the extra dynamic allocation and the addition of a null terminator (because std::string has a constructor that accepts a length argument for just this sort of occasion).

The various char can be aliased, so simply:

std::string string_from_uchar(const unsigned char * c, unsigned long long lc)
{
    return std::string((const char*)c, lc);
}

In fact, if you use the constructor that takes a range, you don't even need the cast:

std::string string_from_uchar(const unsigned char * c, unsigned long long lc)
{
    return std::string(c, c + lc);
}

It barely even warrants being in its own function.

Upvotes: 5

Related Questions