Re: serialization class and endian



slebetman@xxxxxxxxx wrote:
toby wrote:
...
Well, again htonl() and htons() are completely redundant, since the
decomposition of an integer into bytes already explicitly defines an
ordering. I assumed you realised that these functions really only apply
if you are storing shorts/longs and then treating them as a binary
aggregate for I/O. Not useful for *byte-by-byte* processing of single
values.

See my other post. Docomposition of a 16 bit value 0x1a2b into bytes on
a big endian machines results in the byte stream: 0x1a, 0x2b while on a
little endian machine results in a byte stream 0x2b, 0x1a.

Only if you try to examine the short/long typed datum as a byte series,
which the code I posted does not do.


By "decomposition" I'm assuming you mean:

unsigned char bytes[2];
unsigned short number = 0x1a2b;
memcpy(&bytes[0], &number, 2);

No, I don't mean that. I gave a portable method above, similar to what
you had in mind below.


or the slightly less portable:

unsigned char *bytes;
unsigned short number = 0x1a2b;
bytes = (char *)&number;

No, I don't mean that either.


The above codes will result in different bytestreams depending on the
endianness of the machine. On their own they are quite harmless until
you try to transmit the bytes between a big endian machine and a little
endian machine.

Of course.


You mentioned before about "specifying" the order of the transmitted
bytes. This basically amounts to writing code to convert from the
transmission order to the native machine order. Trying to do this
portably:

void short2bigEndian(char *bytes, unsigned short number) {
// Note that C's math and logic operators are
// endian neutral.They work on the numerical
// 'value' not representation. So the following
// works on both big and little endian machines:
bytes[0] = number & 0xff00;

You're missing a shift here.

bytes[1] = number & 0x00ff;
}

But why would you need to write that when all TCP/IP libraries already
implement htons?

You *have* to do it by manual value decomposition if you're dealing
with a byte stream (i.e. you cannot write aggregates). (Sorry to repeat
myself, but in this case hton[sl]() just cannot help in this
situation.)

On the other hand, you *would* use htons() if you were doing this:
short outvalue = htons(invalue);
fwrite(*outvalue,sizeof(short),1,file);
(Or if you were writing a structure containing short/long fields.)

But the OP is encoding as a string (assuming he meant binary not ASCII
- he seems confused on this question), so I alternatively proposed
above:
std::string str;
str += (char)(invalue >> 8); // use BigEndian ordering
str += (char)invalue;
Which is of course portable.

On little endian machines htons() will simply filp the
bytes around using the most optimal algorithm for the platform but on
big endian machines htons() typically gets optimised to nothing when
compiled (since the bytes are already in the right order). Using
htons() simply allows your code to work on big and little endian
machines without modification.

But both calls are, as I say above, only useful in the case you're
treating shorts and longs as aggregates - not if you are building an
encoding byte by byte.

.



Relevant Pages

  • Re: serialization class and endian
    ... Well, again htonland htons() are completely redundant, since the ... a big endian machines results in the byte stream: ... encoding byte by byte is: ... this only works if the type of invalue is actually ...
    (comp.programming)
  • Re: serialization class and endian
    ... Well, again htonland htons() are completely redundant, since the ... a big endian machines results in the byte stream: ... std::string str; ... encoding byte by byte is: ...
    (comp.programming)
  • Re: serialization class and endian
    ... Well, again htonland htons() are completely redundant, since the ... a big endian machines results in the byte stream: ... std::string str; ... encoding byte by byte is: ...
    (comp.programming)