-1

I have a vector of unsigned char where I copy bytes in C++. I convert all primitive types to bytes and copy to this vector of char (which is interpreted as bytes in C++). Now I am copying also strings. But I am not sure if I am converting strings to bytes. If you take a look at my output when I am printing the vector of unsigned char I am printing bytes from double int float but I am printing the real string of my variable testString. So I suppose that I am not inserting bytes of this testString on my vector of unsigned char. How should I do that? Thanks

    const std::string lat = "lat->", alt = "alt->", lon = "lon->", testString = "TEST-STRING";
    double latitude = 10.123456;
    double longitude = 50.123456;
    double altitude = 1.123456;

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

    std::cout << "copying to the vector" << std::endl;
    memcpy(result.data(), &longitude, sizeof(longitude));
    memcpy(result.data() + sizeof(longitude), &latitude, sizeof(latitude));
    memcpy(result.data() + sizeof(longitude) + sizeof(latitude), &altitude, sizeof(altitude));
    memcpy(result.data() + sizeof(longitude) + sizeof(latitude) + sizeof(altitude), testString.c_str(),
           testString.length() + 1);
    std::cout << "copied to the vector\n" << std::endl;

    std::cout << "printing the vector" << std::endl;
    for (unsigned 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 dLat, dLon, dAlt;
    std::string value;

    memcpy(&dLon, result.data(), sizeof(longitude));
    memcpy(&dLat, result.data() + sizeof(longitude), sizeof(latitude));
    memcpy(&dAlt, result.data() + sizeof(longitude) + sizeof(latitude), sizeof(altitude));
    value.resize(testString.length());
    memcpy(&value[0], result.data() + sizeof(longitude) + sizeof(latitude) + sizeof(altitude),
           sizeof(value.data()) + testString.size());

    std::cout << alt << dAlt;
    std::cout << lat << dLat;
    std::cout << lon << dLon;
    std::cout << " " << value << std::endl;
    std::cout << "printed back the original value\n" << std::endl; 

output:

copying to the vector
copied to the vector

printing the vector
[?�gI@m���5?$@l������?TEST-STRING
printed the vector

printing back the original value
alt->1.12346lat->10.1235lon->50.1235 TEST-STRING
printed back the original value
Felipe
  • 7,013
  • 8
  • 44
  • 102
  • 1
    I'm not sure what you're asking. A C string is a sequence of bytes (and a `char` is a byte). – melpomene Oct 19 '18 at 07:57
  • result is a vector of char. What is cout going to do with a char if not print the char? It's exactly what would be expected, no? – Rags Oct 19 '18 at 07:58
  • I convert values to a vector of char and after I convert back. – Felipe Oct 19 '18 at 08:01
  • "*after I convert back.*"... Converting larger types (double, float, etc.) to lower types (char, short, etc.) makes you lose precision... When you will convert the characters back to their acutal values.. You might not know when they became something else... (That is, a char is only 255 bytes and no more, if you want more, use *wchar_t*)... – Ruks Oct 19 '18 at 08:02
  • 1
    There are also a few errors: you need an extra byte in the `vector` since you are copying the `\0` character of the string. Further, `sizeof(value.data())` does not make sense, because that is the size of a pointer. – Acorn Oct 19 '18 at 08:03
  • @Ruks This has nothing to do with conversions, though. – Acorn Oct 19 '18 at 08:04
  • @Acorn... Why not??... It is literally an explanation of the conversion between a double, float or some other type when changed to char. – Ruks Oct 19 '18 at 08:10
  • Having a look at [IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) might explain why your printed raw data differs so much from what you might have expected... Be aware that C++ does not require (as neither does C) floating point variables to follow that norm, but most systems do; actually, I am not aware of a single current one that doesn't. – Aconcagua Oct 19 '18 at 08:21
  • @Ruks Because OP is, on purpose, copying the underlying representation of the `double` etc. objects; not converting its values into another type. – Acorn Oct 19 '18 at 08:37

2 Answers2

4

There's no problem with your code! You're printing the actual bytes of your variables. The bytes in a double can't really be interpreted as a text string (at least, it doesn't make sense if you do) but the bytes in a text string can, producing what you see.

Let's say you've got the following code (which is really just disguised C):

#include <cstdio>

int main(int argc, char *argv[]) {
    struct {
        double latitude;
        double longitude;
        char name[30];
    } structure = {
        53.6344,
        126.5223167,
        "Keyboard Mash"
    };
    printf("%f %f %s\n", structure.latitude, structure.longitude, structure.name);
    for (size_t i = 0; i < sizeof(structure); i += 1) {
        printf("%c", ((char*)&structure)[i]);
    }
    printf("\n");
}

This code would (probably) print:

53.6344 126.5223167 Keyboard Mash
����������������Keyboard Mash�����������������

The first 16 bytes are from the doubles, and the next 30 are from the char[]. That's just how char[]s are stored! Your code is doing what you'd expect it to.

Of course, you can't rely on it doing this in exactly this way; that's undefined behaviour.

wizzwizz4
  • 6,140
  • 2
  • 26
  • 62
  • I liked the way you used `structure`. I am a newbie in C++ and I am going to improve to use it also – Felipe Oct 19 '18 at 08:14
  • 1
    @FelipeOliveiraGutierrez I used it in a bad way to make the code shorter; you should define the `struct` separately to the variable because that's clearer. – wizzwizz4 Oct 19 '18 at 08:15
1

I feel like you were expecting something like: 128565TESTSTRING where 12, 85 and 65 are values of longitude, latitude and altitude. Well, that's not going to happen be cause you wrote 12 in the data, not "12"; therefore, it will return you the character whose ASCII code is 12. Maybe you could use something like sprintf() instead.

PhoenixBlue
  • 967
  • 2
  • 9
  • 26