1

What I want to do should actually be quite simple, but I don't know how to achieve it in a simple way:

I want to copy the value of an unsigned integer (32 Bit) to an array of unsigned chars. The representation inside the array must always be in little endian.

On an little endian architecture I can simple do:

unsigned char array[sizeof(unsigned int)];
unsigned int i = 12345;
memcpy(array, &i, sizeof(unsigned int));

The representation will be in little endian. What is the best way to achieve this on a big endian architecture? And how do I figure out the endianess of my architecture inside my Code?

My project uses the C++11 standard.

Thanks in advance!

rralf
  • 1,202
  • 15
  • 27
  • 4
    One way figuring the endianness out is using htons(). If (0x1234 == htons(0x1234)) you are big endian. – tebe Jan 08 '14 at 16:07
  • 1
    Ad converting to little endian if you are big endian you can always shift bits and use masks. for (j = 0; j < 4; j++) array[j] = i >> ((3-j)*8) & 0xFF; - i think. – tebe Jan 08 '14 at 16:10
  • @tebe in otherwords, calling `i = htons(i)` before the `memcpy` fixes his whole problem. –  Jan 08 '14 at 17:11
  • @ebyrob: the problem with htons() is that if you are compiled on a big endian system it does nothing. As of my understanding the hton.() and ntoh.() functions do not swap the endianness but convert from host endianness to network endianness. – tebe Jan 09 '14 at 00:40
  • @tebe Oh wow, the array is in the opposite of network byte order. So, he wants the opposite output order of `htons()`. I totally missed that part. –  Jan 09 '14 at 14:24
  • That are multiple questions and not just one. So first: How to detect endianess. Take a look [here](http://stackoverflow.com/questions/1001307/detecting-endianness-programmatically-in-a-c-program). Second: How to convert from Big to little endian. Take a look [here](http://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c). Now with your code snippet you should be able to solve your problem. – mkaes Jan 08 '14 at 16:09
  • Given that there are at least three different endianness for 32 bit values (that have actually been used---theoretically, there are 24), I'd say that any answer that depends on detecting endianness is a poor solution. – James Kanze Jan 08 '14 at 16:21

1 Answers1

8

You don't want to "copy" the internal representation of the unsigned int; you want to format it to a specified external representation. This is relatively easy:

*dest ++ = (i      ) & 0xFF;
*dest ++ = (i >>  8) & 0xFF;
*dest ++ = (i >> 16) & 0xFF;
*dest ++ = (i >> 24) & 0xFF;

That is, after all, the definition of a 32 bit little endian representation.

Signed integers can be more complex, because there are different representations of negative numbers, and floating point is even worse. In many cases, it's acceptable to give up some portability: writing a 64 bit IEEE double is decidedly non-trivial if your machine uses some other format (which is the case of most mainframes).

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • I like this one as it is very efficient. And dest always represented in little endian, even if i is big endian? – rralf Jan 08 '14 at 16:24
  • 2
    @rralf if you follow the logic, you can see it doesn't matter what the internal representation is. The output will *always* be little endian. – Mark Ransom Jan 08 '14 at 16:33
  • 2
    Related: Rob Pike's blog post, [The byte order fallacy](http://commandcenter.blogspot.co.uk/2012/04/byte-order-fallacy.html), and Embedded in Academia [Does Portable Byte-Order Code Optimize?](http://blog.regehr.org/archives/702) – John Bartholomew Jan 08 '14 at 16:37