views:

150

answers:

3

Hey, I've written a function to copy any variable type into a byte vector, however whenever I insert something it gets inserted in reverse.

Here's the code.

template <class Type>
void Packet::copyToByte(Type input, vector<uint8_t>&output)
{
    copy((uint8_t*) &input, ((uint8_t*) &input) + sizeof(Type), back_inserter(output));
}

Now whenever I add for example a uint16_t with the value 0x2f1f it gets inserted as 1f 2f instead of the expected 2f 1f.

What am I doing wrong here ?

Regards, Xeross

+8  A: 

If you are on a little-endian machine (e.g., an x86), the bytes will appear reversed (i.e., the lower order bytes will appear before the higher order bytes).

If you really want to reverse the order of the bytes, you can use std::reverse.

James McNellis
How would I be able to check the endianness and act accordingly, is there some kind of way to always make it store everything as big-endian ?Also if I copy it back it will have the wrong value, wouldn't that not be the case with the endians ?
Xeross
@xeross: You can test your platform's endianness at runtime; take a look at http://stackoverflow.com/questions/2531515/can-someone-explain-this-endian-ness-function-for-me
James McNellis
I managed to reverse them successfully, would have to check how exactly but this answer seems to be the closest.
Xeross
A: 

http://en.wikipedia.org/wiki/Endianness

baol
+4  A: 

You're not doing anything wrong. You are working on a little endian machine (e.g. Pentium). On these, the lower significant byte of a multiple bytes value is stored at the smallest address. Hence the result.

Didier Trosset
Potatoswatter
@Potatoswatter: care to elaborate ?
Xeross
@xeros: C++ doesn't allow you to simply cast anything to `char*`. It compiles but has undefined behavior. This is a classic example. And on the other end, you can't cast back. What if the class has pointers?
Potatoswatter
… by the way, the C-style cast here is interpreted as `reinterpret_cast`.
Potatoswatter
@PotatoSwatter: So this would cause problems with pointers and certain data types, I understand that but most of the numeric data types will be accepted by this afaik.If you know a better way to do this I'd be happy to hear your suggestion.
Xeross
@xeross: Serialize into a text format, or binary using `htonl`. But treating data structures as bytestreams is about as unportable as you can get.
Potatoswatter
@PotatoSwatter: Yes I should probably look into specialization for classes or exception variable types, however whenever we encounter a Type that doesn't work with the default template we'll specialize it.
Xeross
@xeross: That strategy is similar to `operator<<` with streams. You might consider using overloading rather than specialization. Also, consider providing a generic `template<class T> serialize(T*input,…);` which is unimplemented, to ensure avoidance of default-serialization of any pointer.
Potatoswatter