Felipe
Felipe

Reputation: 7583

How to use multiple times memcpy to convert back a std::vector<unsigned char>?

I want to convert a set of values which are strings, doubles, and time_t to a std::vector<unsigned char> in C++. I am using memcpy for that and calling it every time that I have a new value. I just realized that I have to call it backward to concatenate on the right order on my vector. After I convert all my values I want to convert back. The way I am doing is calling each time memcpy again to get the original value converted back. But because the values after the first are in the middle of the vector I cannot convert it back properly.

How do I convert back all values from the vector separately? My code is below and the output too. Thanks

int main(void) {
    std::string lat = "lat->";
    double latitude = 13.123456;

    std::vector<unsigned char> result(sizeof(lat) + sizeof(latitude));

    std::cout << "copying to the vector" << std::endl;
    memcpy(result.data(), &latitude, sizeof(latitude)); // add string to the vector
    memcpy(result.data(), &lat, sizeof(result.size()) + sizeof(lat)); // add double to the same vector
    std::cout << "copied to the vector\n" << std::endl;

    std::cout << "printing the vector" << std::endl;
    for (int j = 0; j < result.size(); j++) {
        std::cout << result[j];
    }
    std::cout << std::endl;
    std::cout << "printed the vector\n" << std::endl;

    // testing converting back ...................
    std::cout << "printing back the original value" << std::endl;
    double d;
    std::string value;
    // make sure the vector is the right size
    if (result.size() != (sizeof(d) + sizeof(lat)))
        throw std::runtime_error {
                "Size of data in vector and float do not match" };
    // copy the bytes into the float
    memcpy(&value, result.data(), sizeof(value));
    std::cout << value;
    memcpy(&d, result.data(), sizeof(value) + sizeof(d));
    std::cout << d << std::endl;
    std::cout << "printed back the original value\n" << std::endl;
}

Output:

copying to the vector
copied to the vector

printing the vector
��(�lat->Pş0��(�
printed the vector

printing back the original value
lat->6.95297e-310
printed back the original value

Segmentation fault (core dumped)

Upvotes: 0

Views: 2415

Answers (1)

Walter
Walter

Reputation: 45444

As I said in the comments, don't do that sort of thing unless you know what you're doing (which you didn't).

Writing into the memory buffer:

std::string lat = "lat->";
double latitude = 13.123456;

std::vector<unsigned char> result(lat.length() + sizeof(latitude));

std::cout << "copying to the vector" << std::endl;
std::memcpy(result.data(), &latitude, sizeof(latitude));             // add double
std::memcpy(result.data()+sizeof(latitude), lat.data(), lat.size()); // add raw string data
std::cout << "copied to the vector\n" << std::endl;

Note that the destination pointer passed to memcpy is different for the two calls, pointing each time to memory not previously used.

Care is required when reading back the string with memcpy:

double d;
std::string value;
std::memcpy(&d, result.data(), sizeof(latitude));    // copy back the bytes of the double
value.resize(lat.length());
std::memcpy(value.data(),result.data()+sizeof(latitude), value.data(), lat.size());

You see that we need to know the number of characters (lat.size()) before we can copy them from the buffer. This renders the whole approach questionable at best. I strongly recommend that, after understanding this example, you don't do this sort of thing anymore.

Upvotes: 2

Related Questions