There is a minority view that says if you code properly then you never need to know the endianness of your machine. You should certainly consider carefully if you can do so in your application.
x 04 x+1 03 x+2 02 x+3 01
x 01 x+1 02 x+2 03 x+3 04
x 03 x+1 04 x+2 01 x+3 02
Network byte order is the standard used in packets sent over the internet. It is big-endian (except that technically it refers to the order in which bytes are transmitted, not the order in which they are stored). If you are going to chose an arbitrary order to standardize on, network-byte order is a sensible choice.
The unix functions htonl(), htons(), ntohl(), and ntohs() convert longs and shorts back and forth between the host byte order and network byte order. However, though they are widely available, they are not universally available.
The sys/param.h header normally defines the symbols __BYTE_ORDER, __BIG_ENDIAN, __LITTLE_ENDIAN, and __PDP_ENDIAN. You can test endianness by doing something like:
#include <sys/param.h> #ifdef __BYTE_ORDER # if __BYTE_ORDER == __LITTLE_ENDIAN # define I_AM_LITTLE_ENDIAN # else # if __BYTE_ORDER == __BIG_ENDIAN # define I_AM_BIG_ENDIAN # else Error: unknown byte order! # endif # endif #endif /* __BYTE_ORDER */If __BYTE_ORDER is not defined, you may want to test for the existance of BYTE_ORDER, BIG_ENDIAN and LITTLE_ENDIAN. Linux defines these as synonym of the versions with underscores, apparantly in attempt to be compatible with BSD Unix.
If that is not defined, you might try things like:
#if defined (i386) || defined (__i386__) || defined (_M_IX86) || \ defined (vax) || defined (__alpha) # define I_AM_LITTLE_ENDIAN #endifHowever trying to cover all bases with this sort of thing seems futile, and may be complicated by architectures that can work either way. Ultimately, it is better to fall back to a run-time test.
int am_big_endian() { long one= 1; return !(*((char *)(&one))); }Or an alternate version using unions (based on Harbison & Steele):
int am_big_endian() { union { long l; char c[sizeof (long)]; } u; u.l = 1; return (u.c[sizeof (long) - 1] == 1); }
I suspect that these run-time tests are the better solution.
Byte-order is not determined by the OS you are running, but some OS's have limitations on what processors they will run on. Microsoft's operations systems run almost exclusively on little-endian machines, while Apple's OS 9 ran almost exclusively on big-endian machines. Unix (including OS X) works perfectly fine either way, which is why detecting endian-ness is something Unix programmers occasionally need to know how to do. For what it's worth, I'd guess most Unixes these days are on x86 processors, so Unix is probably more commonly little-endian than big-endian.
Creative, but wrong. The names are derived from Jonathon Swift's book Gulliver's Travels, where they describe Lilliputian political parties who disagree vehemently over which end to start eating an egg from. This terminology was popularized for byte order by a less than completely serious paper authored by Danny Cohen which appeared on April 1, 1980 and was entitled "On Holy Wars and a Plea for Peace" (google the title to find a copy).
Only sort of. The PDP-11 didn't have instructions to store 32-bit values to memory, so the particular weird "middle-endian" value couldn't possibly apply to the way it stored values in memory. It stored 16-bit values to memory in the usual little endian manner. It could do 32-bit arithmatic, storing the values in pairs of 16-bit CPU registers (not memory). The most signficant word went into the lower numbered register, but within each register values were stored little-endian. So that could be viewed as "middle-endian", but in a sense that could only matter to assembly language programmers and compiler writers, whose code could never hope to be portable anyway.