Vlad Dogaru <dd****@gmail.comwrites:
On May 2, 7:52 pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
> memcpy(&char_buf, &int_var, sizeof int_var);
[snip]
The shifting method (used on unsigned types) can give you
a portable solution.
Would memcpy and htons & co be a correct approach?
First htons and htnol (the "long" version) are POSIX, so technically
off topic here. They are an excellent choice for this problem but
they incur a cost that can be avoided if you are designing a system
for CPUs where the "host" representation is different to the "network"
one. If you can use you own functions, you can avoid this (probably
small) cost by making these operations "null" on your main platform.
My problem is that
it's not only short ints that I have to accomodate, but also the
occasional long; I'd like to have a uniform handling of these
operations.
Then there is htonl and ntohl that take uint32_t values. Note that C
does not insist that long is 32 bits, but uint32_t is.
Also, I'm not sure if the way I found to "deserialize" these values is
safe and recommended:
x = htons(x);
memcpy(&buffer, &x, sizeof x);
That is the safe, portable, way. However, a lot of code will be able
to define the buffer as struct with integer members, so one often
sees:
msg.data1 = htons(x);
or even, the more dangerous:
*(uint16_t *)buffer = htons(x);
The memcpy version avoids any alignment problems and so it more portable.
/* Later, at the other end: */
x = ntohs(*((unsigned short *) buffer));
The reverse would have been
memcpy(&x, &buffer, sizeof x);
x = htons(x);
but the dangerous cast is often used. Data formats in protocols are
often chosen so that there will be no alignment problems on most
common processors, so you will have to decide between portability,
code clarity and speed of packing knowing what you know about the
target systems and the purpose of the code.
I only need unsigned values, so unsigned {short, long} should be
enough. And one final question: would there be any reason to using
uint16_t and uint32_t instead of unsigned short and unsigned long?
Yes. The most important is that POSIX now defines the [nh]to[hn][ls]
functions in terms of these types. These days, you are more likely
to find a system where short 16 bits or long 32 bits than you are
to find one where uint32_t is either not defined or is hard to define
yourself.
--
Ben.