Search code examples
c++castingcharbufferunsigned

char array to uint8_t array


this is one area of C/C++ that i have never been good at.

my problem is that i have a string that will need to eventually contain some null characters. treating everything as a char array (or string) won't work, as things tend to crap out when they find the first null. so i thought, ok, i'll switch over to uint8_t, so everything is just a number. i can move things around as needed, and cast it back to a char when i'm ready.

my main question right now is: how can i copy a portion of a string to an uint8_t buffer?

effectively, i'd like to do something like:

std::string s = "abcdefghi";
uint8_t *val = (uint8_t*)malloc(s.length() + 1);
memset(val, 0, s.length() + 1);

// Assume offset is just some number
memcpy(val + offset, s.substr(1, 5).c_str(), 5);

obviously, i get an error when i try this. there is probably some sort of trickery that can be done in the first argument of the memcpy (i see stuff like (*(uint8_t*)) online, and have no clue what that means).

any help on what to do?

and while i am here, how can i easily cast this back to a char array? just static_cast the uint8_t pointer to a char pointer?

thanks a lot.


Solution

  • i thought, ok, i'll switch over to uint8_t, so everything is just a number.

    That's not going to make algorithms that look for a '\0' suddenly stop doing it, nor do algorithms that use char have to pay attention to '\0'. Signaling the end with a null character is a convention of C strings, not char arrays. uint8_t might just be a typedef for char anyway.

    As Nicol Bolas points out std::string is already capable of storing strings that contain the null character without treating the null character specially.

    As for your question, I'm not sure what error you're referring to, as the following works just fine:

    #include <iostream>
    #include <string>
    #include <cstdint>
    #include <cstring>
    
    int main() {
        std::string s = "abcdefghi";
        std::uint8_t *val = (std::uint8_t*)std::malloc(s.length() + 1);
        std::memset(val, 0, s.length() + 1);
    
        int offset = 2;
        std::memcpy(val + offset, s.substr(1, 5).c_str(), 5);
        std::cout << (val+offset) << '\n';
    }
    

    The memcpy line takes the second through sixth characters from the string s and copies them into val. The line with cout then prints "bcdef".

    Of course this is C++, so if you want to manually allocate some memory and zero it out you can do so like:

    std::unique_ptr<uint8_t[]> val(new uint8_t[s.length()+1]());
    

    or use a vector:

    std::vector<uint8_t> val(s.length()+1,0);
    

    To cast from an array of uint8_t you could (but typically shouldn't) do the following:

    char *c = reinterpret_cast<uint8_t*>(val);